{"record":{"id":"a7cfb973c211f512","repo":"bevyengine/bevy","slug":"asset-path-0-is-unapproved-see-unapprovedpath","errorCode":null,"errorMessage":"Asset path \"{0}\" is unapproved. See UnapprovedPathMode for details.","messagePattern":"Asset path \"(.+?)\" is unapproved\\. See UnapprovedPathMode for details\\.","errorType":"error_code","errorClass":"AssetLoadError::UnapprovedPath","httpStatus":null,"severity":"error","filePath":"crates/bevy_asset/src/server/mod.rs","lineNumber":2230,"sourceCode":"    pub path: AssetPath<'static>,\n    /// The requested type id of handle.\n    pub requested: TypeId,\n    /// The actual loaded asset type name.\n    pub actual_asset_name: &'static str,\n    /// The loader name used to load the asset.\n    pub loader_name: &'static str,\n}\n\n/// An error that occurs during an [`Asset`] load.\n#[derive(Error, Debug, Clone)]\n#[expect(\n    missing_docs,\n    reason = \"Adding docs to the variants would not add information beyond the error message and the names\"\n)]\npub enum AssetLoadError {\n    #[error(\"Attempted to load an asset with an empty path \\\"{0}\\\".\")]\n    EmptyPath(AssetPath<'static>),\n    #[error(\"Asset path \\\"{0}\\\" is unapproved. See UnapprovedPathMode for details.\")]\n    UnapprovedPath(AssetPath<'static>),\n    #[error(transparent)]\n    RequestedHandleTypeMismatch(#[from] Box<RequestedHandleTypeMismatchError>),\n    #[error(\"Could not find an asset loader matching: Asset Type: {asset_type_id:?}; Path: {asset_path:?};\")]\n    MissingAssetLoader {\n        asset_type_id: Option<TypeId>,\n        asset_path: String,\n    },\n    #[error(transparent)]\n    MissingAssetLoaderForExtension(#[from] MissingAssetLoaderForExtensionError),\n    #[error(transparent)]\n    MissingAssetLoaderForTypeName(#[from] MissingAssetLoaderForTypeNameError),\n    #[error(transparent)]\n    MissingAssetLoaderForTypeIdError(#[from] MissingAssetLoaderForTypeIdError),\n    #[error(transparent)]\n    AssetReaderError(#[from] AssetReaderError),\n    #[error(transparent)]\n    MissingAssetSourceError(#[from] MissingAssetSourceError),","sourceCodeStart":2212,"sourceCodeEnd":2248,"githubUrl":"https://github.com/bevyengine/bevy/blob/227d3a6c661b3bdf3020d3e8290b5a6ffd0226f7/crates/bevy_asset/src/server/mod.rs#L2212-L2248","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add the path's directory prefix to AssetPlugin::approved_path_prefixes in app setup","Fix the asset path so it lives under an approved prefix","If approval is not needed, set AssetPlugin::unapproved_path_mode to UnapprovedPathMode::AllowedWarn or Allowed","Verify the exact requested path (from the error's AssetPath) against the configured prefixes"],"exampleFix":"// before\nApp::new()\n    .add_plugins(DefaultPlugins.set(AssetPlugin {\n        unapproved_path_mode: UnapprovedPathMode::Error,\n        ..default()\n    }))\n    // loading \"scenes/enemy.glb\" -> UnapprovedPath error\n// after\nApp::new()\n    .add_plugins(DefaultPlugins.set(AssetPlugin {\n        unapproved_path_mode: UnapprovedPathMode::Error,\n        approved_path_prefixes: vec![\"assets/scenes\".into()],\n        ..default()\n    }))","handlingStrategy":"validation","validationCode":"fn is_path_approved(path: &str, prefixes: &[String]) -> bool {\n    prefixes.iter().any(|p| path.starts_with(p.as_str()))\n}","typeGuard":"fn starts_with_any<'a>(path: &'a str, prefixes: &[&'a str]) -> Option<&'a str> {\n    prefixes.iter().copied().find(|p| path.starts_with(*p))\n}","tryCatchPattern":"match server.load_checked(path) {\n    Ok(handle) => handle,\n    Err(AssetLoadError::UnapprovedPath(p)) => {\n        error!(\"path {p:?} not under approved prefixes\");\n        Handle::default()\n    }\n    Err(e) => panic!(\"asset load failed: {e}\"),\n}","preventionTips":["List all asset directories in approved_path_prefixes when enabling approval","Centralize asset paths in a constants module so prefixes stay consistent","Run CI builds with UnapprovedPathMode::Error to catch stray paths early","When moving assets to a new folder, update the approved prefixes in the same commit"],"tags":["bevy","assets","path-validation","security"],"backgroundTag":"unapproved-asset-path","analyzedSha":"227d3a6c661b3bdf3020d3e8290b5a6ffd0226f7","analyzedAt":"2026-08-30T08:55:11.013Z","contentChangedAt":"2026-08-30T08:55:11.013Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}