bevyengine/bevy · error

Field name should be a valid tuple index

Error message

Field name should be a valid tuple index

What it means

ImageSaver with the default FromExtension setting resolved an extension from the destination path, but bevy's ImageFormat::from_extension does not recognize it (crates/bevy_image/src/saver.rs:40-41). The unrecognized extension string is carried in the error. Saving stops because there is no format to encode with.

Source

Thrown at crates/bevy_animation/src/animation_curves.rs:259

    }
}

impl<C: Typed, P, F: Fn(&mut C) -> &mut P + 'static> AnimatedField<C, P, F> {
    /// Creates a new instance of [`AnimatedField`]. This operates under the assumption that
    /// `C` is a reflect-able struct, and that `field_name` is a valid field on that struct.
    ///
    /// # Panics
    /// If the type of `C` is not a struct or if the `field_name` does not exist.
    pub fn new_unchecked(field_name: &str, func: F) -> Self {
        let field_index;
        if let TypeInfo::Struct(struct_info) = C::type_info() {
            field_index = struct_info
                .index_of(field_name)
                .expect("Field name should exist");
        } else if let TypeInfo::TupleStruct(struct_info) = C::type_info() {
            field_index = field_name
                .parse()
                .expect("Field name should be a valid tuple index");
            if field_index >= struct_info.field_len() {
                panic!("Field name should be a valid tuple index");
            }
        } else {
            panic!("Only structs are supported in `AnimatedField::new_unchecked`")
        }

        Self {
            func,
            evaluator_id: Hashed::new((TypeId::of::<C>(), field_index)),
            marker: PhantomData,
        }
    }
}

/// This trait collects the additional requirements on top of [`Curve<T>`] needed for a
/// curve to be used as an [`AnimationCurve`].
pub trait AnimationCompatibleCurve<T>: Curve<T> + Debug + Clone + Reflectable {}

View on GitHub (pinned to 396ca72708)

Solutions

  1. Rename the destination to an extension bevy recognizes, such as .png (also .jpg/.jpeg/.gif/.tga/.tiff/.webp etc. for ImageFormat)
  2. Pass the format explicitly if the format is supported but its extension is unusual: ImageSaverSettings { format: SaveImageFormatSetting::Format(ImageFormat::Png) }
  3. Check ImageFormat::from_extension at build time for every path you generate

Example fix

// before
let path = AssetPath::from_path(Path::new("icon.bmp"));

// after
let path = AssetPath::from_path(Path::new("icon.png"));
// or keep the name but pin the format:
let settings = ImageSaverSettings {
    format: SaveImageFormatSetting::Format(ImageFormat::Png),
};
Defensive patterns

Strategy: validation

Validate before calling

use bevy_image::ImageFormat;

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

Type guard

fn is_saveable_extension(ext: &str) -> bool {
    // only PNG is actually writable today
    matches!(ext.to_ascii_lowercase().as_str(), "png")
}

Try / catch

match result {
    Err(SaveImageError::UnknownExtension(ext)) => warn!("unknown extension '{ext}', rename to .png"),
    other => other?,
}

Prevention

When it happens

Trigger: Saving to a path whose extension is not in bevy's ImageFormat extension table, e.g. "icon.bmp", "art.svg", "tex.pic" — ImageFormat::from_extension(extension) returns None and UnknownExtension(extension) is returned.

Common situations: Using image formats that bevy can load but not name from extension, or non-image extensions (".tmp", ".dat", ".svg"); generating files with custom suffixes; case-mangled or compound suffixes like "tex.v2".

Related errors


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