Skip to content

NestedLoader can panic from UnapprovedPathMode #21584

@MickHarrigan

Description

@MickHarrigan

Bevy version and features

v0.18.0-dev @ c392d28d

Relevant system information

MacOS 15.6.1 M4 Max

$ cargo --version
cargo 1.89.0 (c24e10642 2025-06-23)

What you did

Example here.

$ cargo run --example asset_folder

Trying to load a path that is unapproved from the NestedLoader<'_,'_, StaticTyped, Deferred> returns a default Handle, which is later unwrapped.

let handle = if self.load_context.should_load_dependencies {
self.load_context.asset_server.load_with_meta_transform(
path,
self.meta_transform,
(),
true,
)
} else {
self.load_context
.asset_server
.get_or_create_path_handle(path, self.meta_transform)
};
// `load_with_meta_transform` and `get_or_create_path_handle` always returns a Strong
// variant, so we are safe to unwrap.
let index = (&handle).try_into().unwrap();

Specifically line 507.

pub(crate) fn load_with_meta_transform<'a, A: Asset, G: Send + Sync + 'static>(
&self,
path: impl Into<AssetPath<'a>>,
meta_transform: Option<MetaTransform>,
guard: G,
override_unapproved: bool,
) -> Handle<A> {
let path = path.into().into_owned();
if path.is_unapproved() {
match (&self.data.unapproved_path_mode, override_unapproved) {
(UnapprovedPathMode::Allow, _) | (UnapprovedPathMode::Deny, true) => {}
(UnapprovedPathMode::Deny, false) | (UnapprovedPathMode::Forbid, _) => {
error!("Asset path {path} is unapproved. See UnapprovedPathMode for details.");
return Handle::default();
}
}
}
let mut infos = self.write_infos();
let (handle, should_load) = infos.get_or_create_path_handle::<A>(
path.clone(),
HandleLoadingMode::Request,
meta_transform,
);
if should_load {
self.spawn_load_task(handle.clone().untyped(), path, infos, guard);
}
handle
}

What went wrong

This causes a panic in the IoTaskPool along with a failure to actually get the handle.

2025-10-17T19:08:37.005590Z ERROR bevy_asset::server: Asset path /tmp/bevy/examples/asset/folder/assets/primary/first.txt is unapproved. See UnapprovedPathMode for details.

thread 'IO Task Pool (3)' panicked at /tmp/bevy/crates/bevy_asset/src/loader_builders.rs:321:42:
called `Result::unwrap()` on an `Err` value: UuidNotSupportedError
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2025-10-17T19:08:37.056995Z ERROR bevy_asset::server: Failed to load asset 'primary', asset loader 'asset_folder::MyAssetLoader' panicked

Additional information

I haven't dug into the other NestedLoader types to see if the same or similar problems exist in those.

My reproduction example is already pretty non-standard and has other issues, explained below.

Example

In the case of setting UnapprovedPathMode::Allow and calling FolderLoader directly, everything is fine.

Else if UnapprovedPathMode is not Allow the crash occurs as described above.

Then finally otherwise if trying to use the load_context to load the Folder immediately the handles are seemingly dropped.
This is what I was actually trying to figure out before finding the panic in the first place.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-BugAn unexpected or incorrect behaviorS-Needs-TriageThis issue needs to be labelled

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions