bevyengine/bevy · error · GltfError

failed to decode base64 mesh data

Error message

failed to decode base64 mesh data

What it means

GltfError::Base64Decode (#[from] base64::DecodeError) comes from DataUri::decode (loader/mod.rs:1989-1995) when a buffer or image embedded as a "data:...;base64," URI cannot be decoded. The decoder used is base64::engine::general_purpose::STANDARD, so the payload must use the standard alphabet (+, /) with correct padding and no whitespace.

Source

Thrown at crates/bevy_gltf/src/loader/mod.rs:99

pub const MAX_JOINTS: usize = 256;

/// An error that occurs when loading a glTF file.
#[derive(Error, Debug)]
pub enum GltfError {
    /// Unsupported primitive mode.
    #[error("unsupported primitive mode")]
    UnsupportedPrimitive {
        /// The primitive mode.
        mode: Mode,
    },
    /// Invalid glTF file.
    #[error("invalid glTF file: {0}")]
    Gltf(#[from] gltf::Error),
    /// Binary blob is missing.
    #[error("binary blob is missing")]
    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.

View on GitHub (pinned to 396ca72708)

Solutions

  1. Re-encode the payload with standard base64 (padding on): `base64 -w0 file.bin` then rebuild the URI.
  2. Prefer moving large buffers out of data URIs into an external .bin or GLB (also smaller in memory).
  3. Verify the segment after the comma decodes: `echo <payload> | base64 -d > /dev/null`.

Example fix

// (before) URL-safe alphabet, no padding
"uri": "data:application/octet-stream;base64,a-b_cd"
// (after) standard alphabet + padding
"uri": "data:application/octet-stream;base64,a+b/cd=="
Defensive patterns

Strategy: validation

Validate before calling

fn data_uris_decode(json: &serde_json::Value) -> Result<(), String> {
    use base64::Engine;
    for uri in json["buffers"].as_array().unwrap_or(&vec![]).iter()
        .filter_map(|b| b["uri"].as_str())
        .filter(|u| u.starts_with("data:")) {
        let payload = uri.split(',').nth(1).unwrap_or("");
        base64::engine::general_purpose::STANDARD
            .decode(payload)
            .map_err(|e| format!("bad base64 buffer: {e}"))?;
    }
    Ok(())
}

Try / catch

match err {
    GltfError::Base64Decode(e) => {
        error!("embedded data URI is not standard base64: {e}");
    }
    other => return Err(other.into()),
}

Prevention

When it happens

Trigger: A buffer/image data URI containing URL-safe base64 ('-' or '_'), missing '=' padding, embedded newlines/spaces, or a truncated payload; the '?' at mod.rs:1939 (buffers) and mod.rs:1247 (images) propagates the DecodeError.

Common situations: Models produced by web tooling that emits URL-safe base64; minifiers stripping padding; copy-paste truncation of very long data URIs; hand-embedding meshes as data URIs.

Understand the failure class

Related errors


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/d12f67ae62f7891d. Report an issue: GitHub.