bevyengine/bevy · error · GltfError
invalid image uri: {0}. asset path error={1}
Error message
invalid image uri: {0}. asset path error={1} What it means
Raised at loader/mod.rs:1261-1263 when a texture's source is a plain URI (not a data:) and LoadContext::resolve_embed_str(uri) fails, producing InvalidImageUri(uri, ParseAssetPathError). Like buffers, image URIs must resolve to a child path of the glTF asset; absolute URLs/paths or malformed relative references fail here.
Source
Thrown at crates/bevy_gltf/src/loader/mod.rs:115
MissingBlob,
/// Decoding the base64 mesh data failed.
#[error("failed to decode base64 mesh data")]
Base64Decode(#[from] base64::DecodeError),
/// Unsupported buffer format.
#[error("unsupported buffer format")]
BufferFormatUnsupported,
/// The buffer URI was unable to be resolved with respect to the asset path.
#[error("invalid buffer uri: {0}. asset path error={1}")]
InvalidBufferUri(String, ParseAssetPathError),
/// Invalid image mime type.
#[error("invalid image mime type: {0}")]
#[from(ignore)]
InvalidImageMimeType(String),
/// Error when loading a texture. Might be due to a disabled image file format feature.
#[error("You may need to add the feature for the file format: {0}")]
ImageError(#[from] TextureError),
/// The image URI was unable to be resolved with respect to the asset path.
#[error("invalid image uri: {0}. asset path error={1}")]
InvalidImageUri(String, ParseAssetPathError),
/// Failed to read bytes from an asset path.
#[error("failed to read bytes from an asset path: {0}")]
ReadAssetBytesError(#[from] ReadAssetBytesError),
/// Failed to load asset from an asset path.
#[error("failed to load asset from an asset path: {0}")]
AssetLoadError(#[from] AssetLoadError),
/// Missing sampler for an animation.
#[error("Missing sampler for animation {0}")]
#[from(ignore)]
MissingAnimationSampler(usize),
/// Failed to generate tangents.
#[error("failed to generate tangents: {0}")]
GenerateTangentsError(#[from] bevy_mesh::GenerateTangentsError),
/// Failed to generate morph targets.
#[error("failed to generate morph targets: {0}")]
MorphTarget(#[from] bevy_mesh::morph::MorphBuildError),
/// Circular children in NodesView on GitHub (pinned to 396ca72708)
Solutions
- Download the textures and point uris at files shipped next to the model ("textures/albedo.png").
- Keep the exporter's directory layout untouched.
- Use '/' separators and relative paths.
- Prefer GLB with embedded textures for portable assets.
Example fix
// (before)
"images": [{ "uri": "https://cdn.example.com/albedo.png" }]
// (after)
"images": [{ "uri": "textures/albedo.png" }] Defensive patterns
Strategy: validation
Validate before calling
fn image_uris_local(json: &serde_json::Value) -> bool {
json["images"].as_array().unwrap_or(&vec![]).iter()
.filter_map(|i| i["uri"].as_str())
.filter(|u| !u.starts_with("data:"))
.all(|u| !u.contains("://") && !u.starts_with('/'))
} Try / catch
match err {
GltfError::InvalidImageUri(uri, e) => {
error!("image uri {uri} cannot resolve under the asset path ({e}); ship the texture next to the model");
}
other => return Err(other.into()),
} Prevention
- Keep texture files next to the .gltf with original relative names.
- Replace remote/absolute image uris during import.
- Prefer embedded-texture GLBs for downloadable assets.
When it happens
Trigger: "images": [{ "uri": "https://cdn.example.com/albedo.png" }] or an absolute "/textures/albedo.png"; a relative uri that escapes the asset root; mismatched path separators.
Common situations: Web-origin models keeping CDN texture links; folders reorganized after export; textures renamed without updating the glTF JSON.
Related errors
- invalid buffer uri: {0}. asset path error={1}
- invalid image mime type: {0}
- You may need to add the feature for the file format: {0}
- Field name should exist
- Field name should be a valid tuple index
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/e421a245e06ee21b.
Report an issue: GitHub.