`AssetServer` panics when loading folder
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.
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:/
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 /.
Tbh I think load_folder should accept enum like:
enum Path<'a> {
Relative(&'a str),
Absolute(&'a str)
}
(And then the enum would have relevant impl Into<AssethPath<'a>>)
This way Path::Relative("/") would point to the root of asset folder and Path::Absolute("/") to the root of drive or something
The original "/" and other weird expressions would throw error "malformed path, use Path" or something
EDIT:
The path could be changed to accept another Into<AssethPath<'a>> to have type "support" as load_folder but that would allow recursive paths and I am not sure how that would be handled ?
enum Path<'a, I: Into<AssethPath<'a>>> {
Relative(I),
Absolute(I)
}
Path::Absolute(Path::Relative("data"))
Would navigate to the root of drive (or something else; TODO) and access data folder
while
Path::Relative(Path::Absolute("data"))
Would navigate to the crates assets folder and access data folder
But what about other combinations ?
Or
Path::Relative(Path::Relative("data"))
Would it just get "flattened" too ?