Hmbown/CodeWhale · error
image dimensions exceed the decompression bomb guard…
Error message
image dimensions exceed the decompression bomb guard; downscale or crop first
What it means
An image's declared pixel dimensions (width x height from the header, before full decode) exceed the decompression-bomb guard: the pixel count exceeds MAX_IMAGE_PIXELS or a single dimension exceeds MAX_IMAGE_DIMENSION. The library checks dimensions from the header first so hostile or accidental gigantic images are rejected before allocating decode memory.
Solutions
- Downscale or crop the image so both dimensions and total pixels are under the guard before attaching.
- Re-encode as a reasonably sized JPEG/PNG (e.g. max side ~2048px) with an image tool or ImageMagick.
- If legitimate large images are common, pre-process them at ingestion rather than at attach time.
- For programmatic use, check width*height against MAX_IMAGE_PIXELS before calling the attach API.
Example fix
// before magick input.png attach.png # keeps 18000x12000 // after magick input.png -resize 2048x2048\> attach.png
Defensive patterns
Strategy: validation
Validate before calling
fn header_dims_ok(bytes: &[u8]) -> bool {
ImageReader::new(Cursor::new(bytes))
.into_dimensions()
.map(|(w, h)| {
u64::from(w) * u64::from(h) <= MAX_IMAGE_PIXELS
&& w <= MAX_IMAGE_DIMENSION && h <= MAX_IMAGE_DIMENSION
})
.unwrap_or(false)
} Type guard
fn guarded_dimensions(reader: &ImageReader<Cursor<&[u8]>>) -> Option<(u32, u32)> {
reader.into_dimensions().ok().filter(|(w, h)| {
u64::from(*w) * u64::from(*h) <= MAX_IMAGE_PIXELS
})
} Try / catch
match prepare_tool_image_bytes(&bytes) {
Err(e) if e.to_string().contains("decompression bomb guard") => {
eprintln!("image too large; downscale to <= {} px per side", MAX_IMAGE_DIMENSION); }
other => other?,
} Prevention
- Check header dimensions before decode for any untrusted image
- Downscale on ingestion (e.g. max side 2048) rather than at attach time
- Never decode untrusted images without reader limits set
When it happens
Trigger: decode_and_guard_image is reached with bytes whose header advertises dimensions over the guard — e.g. a 20000x20000 PNG, a panorama, a scaled-up screenshot, or a crafted bomb image — via prepare_runtime_images, prepare_stored_images, prepare_tool_image_bytes, or process_media_file.
Common situations: Attaching a high-resolution camera panorama or scanned poster; a malicious upload designed to exhaust memory; a resized image saved with huge canvas dimensions but tiny content; scientific/medical images that legitimately exceed the dimension cap.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- invalid image header or decompression bomb guard
- agent action=claim widens an enforced write scope, and the…
- allowlisted read-only executable
- append_allow_rules only accepts action = "allow"
- Archive the legacy recording before accepting more…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/eb98f4045a3256d8.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/image_attach.rs:92
pub(crate) fn decode_and_guard_image(bytes: &[u8]) -> Result<(DynamicImage, u32, u32)> {
let limits = || {
let mut limits = Limits::default();
limits.max_alloc = Some(MAX_DECODE_ALLOC_BYTES);
limits.max_image_width = Some(MAX_IMAGE_DIMENSION);
limits.max_image_height = Some(MAX_IMAGE_DIMENSION);
limits
};
let mut reader = ImageReader::new(Cursor::new(bytes)).with_guessed_format()?;
reader.limits(limits());
let (width, height) = reader
.into_dimensions()
.map_err(|_| anyhow::anyhow!("invalid image header or decompression bomb guard"))?;
if u64::from(width) * u64::from(height) > MAX_IMAGE_PIXELS
|| width > MAX_IMAGE_DIMENSION
|| height > MAX_IMAGE_DIMENSION
{
bail!("image dimensions exceed the decompression bomb guard; downscale or crop first");
}
let mut reader = ImageReader::new(Cursor::new(bytes)).with_guessed_format()?;
reader.limits(limits());
let decoded = reader
.decode()
.map_err(|_| anyhow::anyhow!("invalid image content or decode allocation limit"))?;
Ok((decoded, width, height))
}
/// Validate untrusted inline input before route selection or durable admission.
/// Return the existing provider-neutral history representation; no file is opened.
pub(crate) fn prepare_runtime_images(images: &[RuntimeImageInput]) -> Result<Vec<ContentBlock>> {
if images.len() > MAX_RUNTIME_IMAGES {
bail!("images exceed the {MAX_RUNTIME_IMAGES} attachment limit");
}
prepare_images_with_limit(
images,
MAX_RUNTIME_IMAGE_BYTES,View on GitHub (pinned to 73e0f67d83)