sxyazi/yazi · warning
unknown image format
Error message
unknown image format
What it means
ImageInfo::new opens an image file with image::ImageReader::open and with_guessed_format; if the format cannot be determined (reader.format() returns None), the code wraps the failure into an IoError with InvalidData and the message "unknown image format". This means the file could be opened but its magic bytes/content don't match any decoder enabled in the image crate's feature set.
Solutions
- Check the file is actually an image before calling ImageInfo::new (read magic bytes or match the extension against known image formats).
- Enable the required decoder features of the `image` crate (e.g. webp, avif, jpeg, png) in Cargo.toml so with_guessed_format can identify the format.
- Verify the file is not truncated or corrupted (compare size/checksum against the source); re-download or regenerate it.
- Handle the error gracefully and fall back to a generic file preview instead of an image preview.
Example fix
// before
let info = ImageInfo::new(path).await?;
// after
let info = match ImageInfo::new(path).await {
Ok(info) => info,
Err(_) => return Ok(FilePreview::Generic), // not an image (or unsupported format)
}; Defensive patterns
Strategy: fallback
Validate before calling
// Rust
async fn is_probably_image(path: &Path) -> bool {
let magic = |bytes: &[u8]| match bytes {
[0x89, b'P', b'N', b'G', ..] | [0xFF, 0xD8, 0xFF, ..] | b"GIF8"[..].iter().copied().collect::<Vec<_>>().as_slice() if bytes.starts_with(b"GIF8") => true,
[b'B', b'M', ..] | [b'R', b'I', b'F', b'F', ..] => true,
_ => false,
};
tokio::fs::read(path).await.map(|b| b.len() > 11 && magic(&b)).unwrap_or(false)
} Try / catch
match ImageInfo::new(path).await {
Ok(info) => render(info),
Err(e) if e.to_string().contains("unknown image format") => show_generic_preview(),
Err(e) => return Err(e.into()),
} Prevention
- Sniff magic bytes before treating a file as an image.
- Keep image crate decoder features enabled for the formats you expect.
- Never trust file extensions alone.
- Always provide a generic fallback preview.
When it happens
Trigger: Calling ImageInfo::new(path) on a file whose contents don't match a supported format: corrupt/truncated images, text or binary files with an image extension, or formats the image crate was compiled without (feature-gated decoders like webp/avif/heic).
Common situations: A previewer or plugin passes a user-supplied file to ImageInfo without checking the extension/magic bytes; a file is renamed to .png but isn't a PNG; the image crate features were trimmed so a valid image has no decoder; empty or zero-byte files.
Related errors
AI-assisted analysis of sxyazi/yazi@5f901b886b (2026-09-02).
Data as JSON: /api/errors/232bb33febd3706e.
Report an issue: GitHub.
Appendix: source
Thrown at yazi-binding/src/image.rs:22
use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods};
// --- ImageInfo
#[derive(Clone, Copy)]
pub struct ImageInfo {
format: image::ImageFormat,
width: u32,
height: u32,
color: image::ColorType,
orientation: Option<image::metadata::Orientation>,
}
impl ImageInfo {
pub async fn new(path: PathBuf) -> image::ImageResult<Self> {
tokio::task::spawn_blocking(move || {
let reader = image::ImageReader::open(path)?.with_guessed_format()?;
let Some(format) = reader.format() else {
return Err(ImageError::IoError(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"unknown image format",
)));
};
let mut decoder = reader.into_decoder()?;
let (width, height) = decoder.dimensions();
Ok(Self {
format,
width,
height,
color: decoder.color_type(),
orientation: decoder.orientation().ok(),
})
})
.await
.map_err(|e| ImageError::IoError(e.into()))?
}View on GitHub (pinned to 5f901b886b)