GraphiteEditor/Graphite · error · std::io::Error
InvalidData
InvalidData
Error message
Invalid Tiff format
What it means
rawkit's TIFF reader validates the two-byte byte-order marker at the start of the stream: 0x49 0x49 ("II", little-endian) or 0x4D 0x4D ("MM", big-endian). Anything else returns std::io::Error with ErrorKind::InvalidData and this message — the classic "not actually a TIFF" guard. A file shorter than two bytes instead fails read_exact with UnexpectedEof, which is a different error.
Source
Thrown at libraries/rawkit/src/tiff/file.rs:16
use std::io::{Error, ErrorKind, Read, Result, Seek, SeekFrom};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Endian {
Little,
Big,
}
pub struct TiffRead<R: Read + Seek> {
reader: R,
endian: Endian,
}
impl<R: Read + Seek> TiffRead<R> {
pub fn new(mut reader: R) -> Result<Self> {
let error = Error::new(ErrorKind::InvalidData, "Invalid Tiff format");
let mut data = [0_u8; 2];
reader.read_exact(&mut data)?;
let endian = if data[0] == 0x49 && data[1] == 0x49 {
Endian::Little
} else if data[0] == 0x4d && data[1] == 0x4d {
Endian::Big
} else {
return Err(error);
};
reader.read_exact(&mut data)?;
let magic_number = match endian {
Endian::Little => u16::from_le_bytes(data),
Endian::Big => u16::from_be_bytes(data),
};
if magic_number != 42 {
return Err(error);View on GitHub (pinned to c507b35645)
Solutions
- Verify the first bytes: a TIFF starts with II 2A 00 or MM 00 2A
- Sniff the real format (e.g. the image crate's guess_format or file(1)) and route to the correct decoder before calling rawkit
- Re-export or redownload a genuine TIFF if the file is simply the wrong content
Example fix
// before
let tiff = TiffRead::new(Cursor::new(&bytes))?; // any non-TIFF input errors here
// after: verify the TIFF magic before parsing
fn is_tiff(buf: &[u8]) -> bool {
buf.starts_with(b"II\x2A\x00") || buf.starts_with(b"MM\x00\x2A")
}
if !is_tiff(&bytes) {
return Err(Error::new(ErrorKind::InvalidData, "Not a TIFF file"));
}
let tiff = TiffRead::new(Cursor::new(&bytes))?; Defensive patterns
Strategy: validation
Validate before calling
// Read and sniff the header before choosing a decoder
let buf = Vec::new();
file.read_to_end(&mut buf)?;
if !(buf.starts_with(b"II\x2A\x00") || buf.starts_with(b"MM\x00\x2A")) {
return Err(Error::new(ErrorKind::InvalidData, "unsupported image format"));
}
let tiff = TiffRead::new(Cursor::new(buf))?; Type guard
fn is_tiff(buf: &[u8]) -> bool {
buf.starts_with(b"II\x2A\x00") || buf.starts_with(b"MM\x00\x2A")
} Try / catch
// Distinguish "wrong format" from "truncated file" when surfacing to users
match err.kind() {
ErrorKind::InvalidData => show("Unsupported file format"),
ErrorKind::UnexpectedEof => show("File is truncated"),
_ => show("Could not read file"),
} Prevention
- Sniff magic bytes before selecting a decoder; never trust the file extension alone
- Handle UnexpectedEof separately — it means truncation, not a wrong format
- Use a general format sniffer (e.g. image::guess_format) at the import boundary
When it happens
Trigger: TiffRead::new() is handed a JPEG/PNG/WebP or arbitrary binary data; a file renamed to .tif/.tiff with different content; a buffer sliced from the wrong offset so the magic bytes are not at position 0.
Common situations: Format dispatch based on file extension rather than magic bytes; user-supplied uploads trusted by filename; RAW-processing pipelines where the container type is assumed but the payload is something else.
Related errors
- Failed to parse input type for #[implementation(...)]. Expec
- Expected `->` arrow after input type in #[implementations(..
- Failed to parse output type for #[implementation(...)]. Expe
- Failed to parse node_fn attributes: {e}
- Failed to parse implementations for argument '{name}': {e}
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/19a8ac82d04a8f2a.
Report an issue: GitHub.