bevyengine/bevy · error · IntoDynamicImageError
Failed to convert into {0:?}.
Error message
Failed to convert into {0:?}. What it means
IntoDynamicImageError::UnknownConversionError is returned at the tail of Image::try_into_dynamic (image_texture_conversion.rs:189-191) when the format WAS one of the supported ones but ImageBuffer::from_raw returned None. from_raw fails exactly when data.len() != width * height * bytes_per_pixel_of_variant — i.e. the CPU buffer size does not match the image's declared Extent3d. So this variant means internal inconsistency between image.data, image.texture_descriptor.size, and the format, not an unsupported format.
Source
Thrown at crates/bevy_image/src/image_texture_conversion.rs:204
// Throw and error if conversion isn't supported
texture_format => return Err(IntoDynamicImageError::UnsupportedFormat(texture_format)),
}
.ok_or(IntoDynamicImageError::UnknownConversionError(
self.texture_descriptor.format,
))
}
}
/// Errors that occur while converting an [`Image`] into a [`DynamicImage`]
#[non_exhaustive]
#[derive(Error, Debug)]
pub enum IntoDynamicImageError {
/// Conversion into dynamic image not supported for source format.
#[error("Conversion into dynamic image not supported for {0:?}.")]
UnsupportedFormat(TextureFormat),
/// Encountered an unknown error during conversion.
#[error("Failed to convert into {0:?}.")]
UnknownConversionError(TextureFormat),
/// Tried to convert an image that has no texture data
#[error("Image has no texture data")]
UninitializedImage,
}
#[cfg(test)]
mod test {
use image::{GenericImage, Rgba};
use super::*;
#[test]
fn two_way_conversion() {
// Check to see if color is preserved through an rgba8 conversion and back.
let mut initial = DynamicImage::new_rgba8(1, 1);
initial.put_pixel(0, 0, Rgba::from([132, 3, 7, 200]));View on GitHub (pinned to 396ca72708)
Solutions
- Recompute and verify the invariant before converting: data.len() == width * height * pixel_bytes for the format (R8Unorm=1, Rg8Unorm=2, Rgba8UnormSrgb=4).
- Prefer constructing images through Image::new(Extent3d{...}, dimension, data, format, usage), which sets size and data together.
- If you changed data length, update texture_descriptor.size (or recreate the Image) in the same operation.
- Log the expected-vs-actual byte counts when the error fires to find which dimension is stale.
Example fix
// before — size field is stale after data was resized
image.texture_descriptor.size = Extent3d { width: 256, height: 256, depth_or_array_layers: 1 };
image.data = Some(vec![0u8; 250 * 250 * 4]);
let dyn_img = image.try_into_dynamic()?; // Err(UnknownConversionError(Rgba8UnormSrgb))
// after — keep data and extent in sync
let w = 250u32;
let h = 250u32;
let image = Image::new(
Extent3d { width: w, height: h, depth_or_array_layers: 1 },
TextureDimension::D2,
vec![0u8; (w * h * 4) as usize],
TextureFormat::Rgba8UnormSrgb,
RenderAssetUsages::default(),
);
let dyn_img = image.try_into_dynamic()?; Defensive patterns
Strategy: validation
Validate before calling
// check the byte-count invariant before converting
let (w, h) = (image.width(), image.height());
let bpp = match image.texture_descriptor.format {
TextureFormat::R8Unorm => 1,
TextureFormat::Rg8Unorm => 2,
_ => 4,
};
debug_assert_eq!(image.data.as_ref().map(|d| d.len()), Some((w * h * bpp) as usize)); Type guard
fn buffer_consistent(image: &Image) -> bool {
let bpp = match image.texture_descriptor.format {
TextureFormat::R8Unorm => 1,
TextureFormat::Rg8Unorm => 2,
_ => 4,
};
image.data.as_ref().is_some_and(|d| {
d.len() == (image.width() * image.height() * bpp) as usize
})
} Try / catch
match image.try_into_dynamic() {
Err(IntoDynamicImageError::UnknownConversionError(fmt)) => {
// data.len() != w*h*bpp: rebuild the image with matching extent+data via Image::new
}
result => result,
} Prevention
- Create images only via Image::new / new_fill so extent and data stay in sync.
- Never mutate image.data length without updating texture_descriptor.size.
- Debug-assert the data/extent invariant in texture-producing systems.
When it happens
Trigger: Calling try_into_dynamic on an Image assembled by hand with a size field that does not match the data length (e.g. data resized or truncated without updating texture_descriptor.size); mutating image.data in place while keeping stale dimensions; formats where pixel size assumptions differ from what was stored (Rg8Unorm image fed 4-byte-per-pixel data).
Common situations: Manual Image construction for procedural generation/tests where width/height were edited; code copying pixel buffers between images of different sizes; off-by-one row padding when preparing data on the CPU.
Related errors
- Conversion into dynamic image not supported for {0:?}.
- Image has no texture data
- Could not load texture file: {0}
- Error reading image file {path}: {error}.
- missing texture for the font atlas
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/d482a53986a35fb9.
Report an issue: GitHub.