bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
33.44k stars 3.26k forks source link

`AssetServer` panics when loading folder #13946

Open Pieresqi opened 1 week ago

Pieresqi commented 1 week ago

Bevy version

0.14.0-rc.3

[Optional] Relevant system information

SystemInfo { os: "Windows 11 Enterprise", kernel: "22631", cpu: "AMD Ryzen 9 5900X 12-Core Processor", core_count: "12", memory: "63.9 GiB" }

AdapterInfo { name: "NVIDIA GeForce GTX 1080", vendor: 4318, device: 7040, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "555.99", backend: Vulkan }

What you did

I tried loading folder

        let asset_server = world.resource_ref::<AssetServer>();
        asset_server.load_folder("/");

What went wrong

It panicked and wrote into console:

thread 'IO Task Pool (3)' panicked at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_asset-0.14.0-rc.3\src\io\file\file_asset.rs:65:75:
called `Result::unwrap()` on an `Err` value: StripPrefixError(())

While app just ran with this panic I don't think is should panic...

It's intended behaviour ? Maybe write better panic message ??

Additional information

stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d/library\std\src\panicking.rs:652
   1: core::panicking::panic_fmt
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d/library\core\src\panicking.rs:72
   2: core::result::unwrap_failed
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d/library\core\src\result.rs:1654
   3: enum2$<core::result::Result<ref$<std::path::Path>,std::path::StripPrefixError> >::unwrap
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\core\src\result.rs:1077
   4: bevy_asset::io::file::file_asset::impl$0::read_directory::async_fn$0::closure$0::closure$0
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_asset-0.14.0-rc.3\src\io\file\file_asset.rs:65
   5: enum2$<core::option::Option<async_fs::DirEntry> >::and_then<async_fs::DirEntry,std::path::PathBuf,bevy_asset::io::file::file_asset::impl$0::read_directory::async_fn$0::closure$0::closure_env$0>
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\core\src\option.rs:1412
   6: bevy_asset::io::file::file_asset::impl$0::read_directory::async_fn$0::closure$0
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_asset-0.14.0-rc.3\src\io\file\file_asset.rs:57
   7: futures_lite::stream::impl$41::poll_next<async_fs::ReadDir,bevy_asset::io::file::file_asset::impl$0::read_directory::async_fn$0::closure_env$0,std::path::PathBuf>
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\futures-lite-2.3.0\src\stream.rs:2550
   8: futures_core::stream::if_alloc::impl$0::poll_next<dyn$<futures_core::stream::Stream<assoc$<Item,std::path::PathBuf> >,core::marker::Send,core::marker::Unpin> >
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\futures-core-0.3.30\src\stream.rs:209
   9: futures_lite::stream::StreamExt::poll_next<alloc::boxed::Box<dyn$<futures_core::stream::Stream<assoc$<Item,std::path::PathBuf> >,core::marker::Send,core::marker::Unpin>,alloc::alloc::Global> >
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\futures-lite-2.3.0\src\stream.rs:673
  10: futures_lite::stream::impl$22::poll<alloc::boxed::Box<dyn$<futures_core::stream::Stream<assoc$<Item,std::path::PathBuf> >,core::marker::Send,core::marker::Unpin>,alloc::alloc::Global> >
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\futures-lite-2.3.0\src\stream.rs:1909
  11: bevy_asset::server::impl$0::load_folder_internal::load_folder::async_fn$0
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_asset-0.14.0-rc.3\src\server\mod.rs:803
  12: bevy_asset::server::impl$0::load_folder_internal::async_block$0
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_asset-0.14.0-rc.3\src\server\mod.rs:858
  13: async_executor::impl$5::spawn_inner::async_block$0<tuple$<>,enum2$<bevy_asset::server::impl$0::load_folder_internal::async_block_env$0> >
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\async-executor-1.12.0\src\lib.rs:249
  14: core::future::future::impl$1::poll<alloc::boxed::Box<enum2$<async_executor::impl$5::spawn_inner::async_block_env$0<tuple$<>,enum2$<bevy_asset::server::impl$0::load_folder_internal::async_block_env$0> > >,alloc::alloc::Global> >
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\core\src\future\future.rs:123
  15: async_task::raw::impl$3::run::closure$1<core::pin::Pin<alloc::boxed::Box<enum2$<async_executor::impl$5::spawn_inner::async_block_env$0<tuple$<>,enum2$<bevy_asset::server::impl$0::load_folder_internal::async_block_env$0> > >,alloc::alloc::Global> >,tuple$<
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\async-task-4.7.1\src\raw.rs:550
  16: core::ops::function::FnOnce::call_once<async_task::raw::impl$3::run::closure_env$1<core::pin::Pin<alloc::boxed::Box<enum2$<async_executor::impl$5::spawn_inner::async_block_env$0<tuple$<>,enum2$<bevy_asset::server::impl$0::load_folder_internal::async_block
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\core\src\ops\function.rs:250
  17: core::panic::unwind_safe::impl$25::call_once<enum2$<core::task::poll::Poll<tuple$<> > >,async_task::raw::impl$3::run::closure_env$1<core::pin::Pin<alloc::boxed::Box<enum2$<async_executor::impl$5::spawn_inner::async_block_env$0<tuple$<>,enum2$<bevy_asset::
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\core\src\panic\unwind_safe.rs:272
  18: std::panicking::try::do_call<core::panic::unwind_safe::AssertUnwindSafe<async_task::raw::impl$3::run::closure_env$1<core::pin::Pin<alloc::boxed::Box<enum2$<async_executor::impl$5::spawn_inner::async_block_env$0<tuple$<>,enum2$<bevy_asset::server::impl$0::
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\panicking.rs:559
  19: bevy_asset::loader_builders::NestedLoader::new
  20: std::panicking::try<enum2$<core::task::poll::Poll<tuple$<> > >,core::panic::unwind_safe::AssertUnwindSafe<async_task::raw::impl$3::run::closure_env$1<core::pin::Pin<alloc::boxed::Box<enum2$<async_executor::impl$5::spawn_inner::async_block_env$0<tuple$<>,e
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\panicking.rs:523
  21: std::panic::catch_unwind<core::panic::unwind_safe::AssertUnwindSafe<async_task::raw::impl$3::run::closure_env$1<core::pin::Pin<alloc::boxed::Box<enum2$<async_executor::impl$5::spawn_inner::async_block_env$0<tuple$<>,enum2$<bevy_asset::server::impl$0::load
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\panic.rs:149
  22: async_task::raw::RawTask<core::pin::Pin<alloc::boxed::Box<enum2$<async_executor::impl$5::spawn_inner::async_block_env$0<tuple$<>,enum2$<bevy_asset::server::impl$0::load_folder_internal::async_block_env$0> > >,alloc::alloc::Global> >,tuple$<>,async_executo
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\async-task-4.7.1\src\raw.rs:549
  23: async_task::runnable::Runnable<tuple$<> >::run<tuple$<> >
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\async-task-4.7.1\src\runnable.rs:781
  24: async_executor::impl$13::run::async_fn$0::async_block$0<enum2$<core::result::Result<tuple$<>,async_channel::RecvError> >,futures_lite::future::Or<enum2$<bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0::closure$0::async_block_e
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\async-executor-1.12.0\src\lib.rs:740
  25: futures_lite::future::impl$7::poll<enum2$<core::result::Result<tuple$<>,async_channel::RecvError> >,futures_lite::future::Or<enum2$<bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0::closure$0::async_block_env$0>,async_channel::
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\futures-lite-2.3.0\src\future.rs:449
  26: async_executor::impl$13::run::async_fn$0<enum2$<core::result::Result<tuple$<>,async_channel::RecvError> >,futures_lite::future::Or<enum2$<bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0::closure$0::async_block_env$0>,async_cha
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\async-executor-1.12.0\src\lib.rs:747
  27: async_executor::impl$5::run::async_fn$0<enum2$<core::result::Result<tuple$<>,async_channel::RecvError> >,futures_lite::future::Or<enum2$<bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0::closure$0::async_block_env$0>,async_chan
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\async-executor-1.12.0\src\lib.rs:343
  28: futures_lite::future::block_on::closure$0<enum2$<core::result::Result<tuple$<>,async_channel::RecvError> >,enum2$<async_executor::impl$5::run::async_fn_env$0<enum2$<core::result::Result<tuple$<>,async_channel::RecvError> >,futures_lite::future::Or<enum2$<
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\futures-lite-2.3.0\src\future.rs:99
  29: std::thread::local::LocalKey<core::cell::RefCell<tuple$<parking::Parker,core::task::wake::Waker> > >::try_with<core::cell::RefCell<tuple$<parking::Parker,core::task::wake::Waker> >,futures_lite::future::block_on::closure_env$0<enum2$<core::result::Result<
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\thread\local.rs:286
  30: std::thread::local::LocalKey<core::cell::RefCell<tuple$<parking::Parker,core::task::wake::Waker> > >::with<core::cell::RefCell<tuple$<parking::Parker,core::task::wake::Waker> >,futures_lite::future::block_on::closure_env$0<enum2$<core::result::Result<tupl
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\thread\local.rs:262
  31: futures_lite::future::block_on<enum2$<core::result::Result<tuple$<>,async_channel::RecvError> >,enum2$<async_executor::impl$5::run::async_fn_env$0<enum2$<core::result::Result<tuple$<>,async_channel::RecvError> >,futures_lite::future::Or<enum2$<bevy_tasks:
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\futures-lite-2.3.0\src\future.rs:78
  32: bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0::closure$0
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_tasks-0.14.0-rc.3\src\task_pool.rs:176
  33: std::panicking::try::do_call<bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0::closure_env$0,enum2$<core::result::Result<tuple$<>,async_channel::RecvError> > >
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\panicking.rs:559
  34: bevy_tasks::usages::impl$7::deref
  35: std::panicking::try<enum2$<core::result::Result<tuple$<>,async_channel::RecvError> >,bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0::closure_env$0>
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\panicking.rs:523
  36: std::panic::catch_unwind<bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0::closure_env$0,enum2$<core::result::Result<tuple$<>,async_channel::RecvError> > >
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\panic.rs:149
  37: bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_tasks-0.14.0-rc.3\src\task_pool.rs:170
  38: std::thread::local::LocalKey<async_executor::LocalExecutor>::try_with<async_executor::LocalExecutor,bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure_env$0,tuple$<> >
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\thread\local.rs:286
  39: std::thread::local::LocalKey<async_executor::LocalExecutor>::with<async_executor::LocalExecutor,bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure_env$0,tuple$<> >
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\std\src\thread\local.rs:262
  40: bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0
             at C:\Users\Pieresqi\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_tasks-0.14.0-rc.3\src\task_pool.rs:163
  41: core::hint::black_box
             at /rustc/79734f1db8dbe322192dea32c0f6b80ab14c4c1d\library\core\src\hint.rs:338
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
bugsweeper commented 1 week ago

Windows platform doesn't support / path, there is no correct path for entire computer, the path should start from disk letter for local paths like C:/

Aztro-dev commented 1 week ago

I found where the error occurred, and it happens because the read_directory() function in crates/bevy_asset/src/io/file/file_asset.rs tries to run strip_prefix() on the path /home, which has no prefix.

After verifying that the inputted path is a directory (file_asset.rs:53), we get this bit of code:

let root_path = self.root_path.clone();

let mapped_stream = read_dir.filter_map(move |f| {
    f.ok().and_then(|dir_entry| {
        let path = dir_entry.path();
        if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
            if ext.eq_ignore_ascii_case("meta") {
                return None;
            }
        }

        let relative_path = path.strip_prefix(&root_path).unwrap();

        Some(relative_path.to_owned())
    })
});

let read_dir: Box<PathStream> = Box::new(mapped_stream);
Ok(read_dir)

The issue happens when assigning the relative_path variable.

let relative_path = path.strip_prefix(&root_path).unwrap();

Normally, loading a file would look like this: root_path: "/path/to/project/assets" path: "/path/to/project/assets/models/torus/torus.gltf"

In this case, the path is changed to just be models/torus/torus.gltf by running path.strip_prefix(&root_path), and the filter_map goes to the next item.

When you try to load the folder /, this is instead what loading looks like root_path: "/path/to/project/assets" path: "/home"

Running path.strip_prefix(&root_path) here returns an Error type because "/home" does not contain root_path.

\ I think the way to solve this would be to either throw some kind of error warning that trying to load everything in the system is most likely a bad idea, or by using a crate such as pathdiff to get the relative path, which should return a path along the lines of ../../../../../ whenever encountering /.