bevyengine/bevy · error · TextureError

invalid image extension: {0}

Error message

invalid image extension: {0}

What it means

TextureError::InvalidImageExtension is returned by ImageType::to_image_format (crates/bevy_image/src/image.rs:2335-2336) when ImageFormat::from_extension cannot map the extension string to a format. from_extension (image.rs:487) knows a fixed, feature-gated list (png, jpg|jpeg, dds, ktx2, exr, hdr, qoi, ff|farbfeld, basis, ico, gif, bmp, tga, webp, tiff, pam|pbm|pgm|ppm), lowercased before matching; anything else — or a format whose cargo feature is disabled — yields None and this error. The ImageLoader's FromExtension mode hits this path for every asset it loads.

Source

Thrown at crates/bevy_image/src/image.rs:2293

    /// Image extension is invalid.
    #[error("invalid image extension: {0}")]
    InvalidImageExtension(String),
    /// Failed to load an image.
    #[error("failed to load an image: {0}")]
    ImageError(#[from] image::ImageError),
    /// Texture format isn't supported.
    #[error("unsupported texture format: {0}")]
    UnsupportedTextureFormat(String),
    /// Supercompression isn't supported.
    #[error("supercompression not supported: {0}")]
    SuperCompressionNotSupported(String),
    /// Failed to decompress an image.
    #[error("failed to decompress an image: {0}")]
    SuperDecompressionError(String),
    /// Invalid data.
    #[error("invalid data: {0}")]
    InvalidData(String),
    /// Transcode error.
    #[error("transcode error: {0}")]
    TranscodeError(String),
    /// Format requires transcoding.
    #[error("format requires transcoding: {0:?}")]
    FormatRequiresTranscodingError(TranscodeFormat),
    /// Only cubemaps with six faces are supported.
    #[error("only cubemaps with six faces are supported")]
    IncompleteCubemap,
}

/// The type of a raw image buffer.
#[derive(Debug)]
pub enum ImageType<'a> {
    /// The mime type of an image, for example `"image/png"`.
    MimeType(&'a str),
    /// The extension of an image file, for example `"png"`.
    Extension(&'a str),
    /// The direct format of the image

View on GitHub (pinned to 221e52ae32)

Solutions

  1. Convert the asset to a format compiled into your build (PNG is always a safe default) or rename it to a known extension that matches its actual bytes.
  2. Enable the needed cargo feature on bevy/bevy_image for that extension (tga, tiff, webp, bmp, exr, hdr, ico, gif, pnm, ff).
  3. Pin the format explicitly instead of relying on the extension: set ImageLoaderSettings.format = ImageFormatSetting::Format(ImageFormat::Tga) in load_with_settings or in the .meta file.
  4. For custom extensions, load the bytes yourself and call Image::from_buffer with ImageType::Format.

Example fix

// before — build has no "tga" feature, file is hero.tga
let image = server.load("textures/hero.tga"); // load fails: InvalidImageExtension("tga")

// after — enable the feature and/or pin the format explicitly
// Cargo.toml: bevy = { features = ["tga"] }
server.load_with_settings("textures/hero.tga", |s: &mut ImageLoaderSettings| {
    s.format = ImageFormatSetting::Format(ImageFormat::Tga);
});
Defensive patterns

Strategy: validation

Validate before calling

// validate the extension before the loader sees it
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
if ImageFormat::from_extension(ext).is_none() {
    warn!("unsupported image extension {ext:?} for {path:?}");
    return;
}

Type guard

fn extension_supported(ext: &str) -> bool {
    ImageFormat::from_extension(ext).is_some()
}

Try / catch

// in AssetLoadFailedEvent handling:
if let ImageLoaderError::FileTexture(fe) = &*ev.error {
    if let TextureError::InvalidImageExtension(ext) = &fe.error {
        error!("{ext:?} files need a cargo feature or explicit format setting: {}", fe.path);
    }
}

Prevention

When it happens

Trigger: Loading an asset whose file extension is unknown (my_texture.avif) or whose format feature is compiled out (a .tga file in a build without bevy_image's tga feature) via ImageLoader's ImageFormatSetting::FromExtension (image_loader.rs:202-212), or calling Image::from_buffer with ImageType::Extension.

Common situations: Artists deliver .avif/.jxl/.psd files the pipeline cannot decode; bevy default-features = ["png"] builds loading .webp; asset files renamed with wrong extensions; custom asset sources producing nonstandard extensions like "texture.png.bytes".

Related errors


AI-assisted analysis of bevyengine/bevy@221e52ae32 (2026-08-20). Data as JSON: /api/errors/2d9a88ed947d4d47. Report an issue: GitHub.