bevyengine/bevy · error · AssetLoadError::UnapprovedPath

Asset path "{0}" is unapproved. See UnapprovedPathMode for d

Error message

Asset path "{0}" is unapproved. See UnapprovedPathMode for details.

What it means

AssetLoadError::UnapprovedPath is thrown by bevy_asset's AssetServer when a requested asset path is not on the list of approved path prefixes. Depending on AssetPlugin's unapproved_path_mode, unapproved paths are either rejected with this error, warned about, or allowed. It exists to catch accidental loads outside intended asset directories.

Source

Thrown at crates/bevy_asset/src/server/mod.rs:2230

    pub path: AssetPath<'static>,
    /// The requested type id of handle.
    pub requested: TypeId,
    /// The actual loaded asset type name.
    pub actual_asset_name: &'static str,
    /// The loader name used to load the asset.
    pub loader_name: &'static str,
}

/// An error that occurs during an [`Asset`] load.
#[derive(Error, Debug, Clone)]
#[expect(
    missing_docs,
    reason = "Adding docs to the variants would not add information beyond the error message and the names"
)]
pub enum AssetLoadError {
    #[error("Attempted to load an asset with an empty path \"{0}\".")]
    EmptyPath(AssetPath<'static>),
    #[error("Asset path \"{0}\" is unapproved. See UnapprovedPathMode for details.")]
    UnapprovedPath(AssetPath<'static>),
    #[error(transparent)]
    RequestedHandleTypeMismatch(#[from] Box<RequestedHandleTypeMismatchError>),
    #[error("Could not find an asset loader matching: Asset Type: {asset_type_id:?}; Path: {asset_path:?};")]
    MissingAssetLoader {
        asset_type_id: Option<TypeId>,
        asset_path: String,
    },
    #[error(transparent)]
    MissingAssetLoaderForExtension(#[from] MissingAssetLoaderForExtensionError),
    #[error(transparent)]
    MissingAssetLoaderForTypeName(#[from] MissingAssetLoaderForTypeNameError),
    #[error(transparent)]
    MissingAssetLoaderForTypeIdError(#[from] MissingAssetLoaderForTypeIdError),
    #[error(transparent)]
    AssetReaderError(#[from] AssetReaderError),
    #[error(transparent)]
    MissingAssetSourceError(#[from] MissingAssetSourceError),

View on GitHub (pinned to 227d3a6c66)

Solutions

  1. Add the path's directory prefix to AssetPlugin::approved_path_prefixes in app setup
  2. Fix the asset path so it lives under an approved prefix
  3. If approval is not needed, set AssetPlugin::unapproved_path_mode to UnapprovedPathMode::AllowedWarn or Allowed
  4. Verify the exact requested path (from the error's AssetPath) against the configured prefixes

Example fix

// before
App::new()
    .add_plugins(DefaultPlugins.set(AssetPlugin {
        unapproved_path_mode: UnapprovedPathMode::Error,
        ..default()
    }))
    // loading "scenes/enemy.glb" -> UnapprovedPath error
// after
App::new()
    .add_plugins(DefaultPlugins.set(AssetPlugin {
        unapproved_path_mode: UnapprovedPathMode::Error,
        approved_path_prefixes: vec!["assets/scenes".into()],
        ..default()
    }))
Defensive patterns

Strategy: validation

Validate before calling

fn is_path_approved(path: &str, prefixes: &[String]) -> bool {
    prefixes.iter().any(|p| path.starts_with(p.as_str()))
}

Type guard

fn starts_with_any<'a>(path: &'a str, prefixes: &[&'a str]) -> Option<&'a str> {
    prefixes.iter().copied().find(|p| path.starts_with(*p))
}

Try / catch

match server.load_checked(path) {
    Ok(handle) => handle,
    Err(AssetLoadError::UnapprovedPath(p)) => {
        error!("path {p:?} not under approved prefixes");
        Handle::default()
    }
    Err(e) => panic!("asset load failed: {e}"),
}

Prevention

When it happens

Trigger: Calling AssetServer::load/get_handle with a path that does not start with any prefix registered via AssetPlugin::approved_path_prefixes (or set_unapproved_path_mode configuration); loading assets from an unexpected directory in an app that enabled path approval.

Common situations: After enabling unapproved_path_mode for security/reproducibility builds, previously working paths from other directories now fail; typos in the path prefix; assets moved to a new folder not added to approved prefixes; third-party plugins loading assets outside approved roots.

Related errors


AI-assisted analysis of bevyengine/bevy@227d3a6c66 (2026-08-30). Data as JSON: /api/errors/a7cfb973c211f512. Report an issue: GitHub.