{"record":{"id":"0bfcbdbd14d709b6","repo":"Hmbown/CodeWhale","slug":"images-exceed-the-max-runtime-images-attachment-limit","errorCode":null,"errorMessage":"images exceed the {MAX_RUNTIME_IMAGES} attachment limit","messagePattern":"images exceed the (.+?) attachment limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/image_attach.rs","lineNumber":106,"sourceCode":"    if u64::from(width) * u64::from(height) > MAX_IMAGE_PIXELS\n        || width > MAX_IMAGE_DIMENSION\n        || height > MAX_IMAGE_DIMENSION\n    {\n        bail!(\"image dimensions exceed the decompression bomb guard; downscale or crop first\");\n    }\n    let mut reader = ImageReader::new(Cursor::new(bytes)).with_guessed_format()?;\n    reader.limits(limits());\n    let decoded = reader\n        .decode()\n        .map_err(|_| anyhow::anyhow!(\"invalid image content or decode allocation limit\"))?;\n    Ok((decoded, width, height))\n}\n\n/// Validate untrusted inline input before route selection or durable admission.\n/// Return the existing provider-neutral history representation; no file is opened.\npub(crate) fn prepare_runtime_images(images: &[RuntimeImageInput]) -> Result<Vec<ContentBlock>> {\n    if images.len() > MAX_RUNTIME_IMAGES {\n        bail!(\"images exceed the {MAX_RUNTIME_IMAGES} attachment limit\");\n    }\n    prepare_images_with_limit(\n        images,\n        MAX_RUNTIME_IMAGE_BYTES,\n        Some(MAX_RUNTIME_IMAGE_TOTAL_BYTES),\n    )\n}\n\n/// Internal Engine/history input retains the established local 5 MiB ceiling.\n/// Network callers must first pass `prepare_runtime_images` (4 MiB per image,\n/// 10 images and 5 MiB total). Local history never had those aggregate/count\n/// limits; impose only its existing per-image bound and bounded full decode.\npub(crate) fn prepare_stored_images(images: &[RuntimeImageInput]) -> Result<Vec<ContentBlock>> {\n    prepare_images_with_limit(images, MAX_IMAGE_BYTES, None)\n}\n\nfn prepare_images_with_limit(\n    images: &[RuntimeImageInput],","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/image_attach.rs#L88-L124","documentation":"The runtime image attach path enforces MAX_RUNTIME_IMAGES images per call; prepare_runtime_images bails before decoding when more are supplied. This is a hard count limit on inline images admitted into a single request's content blocks.","triggerScenarios":"Calling prepare_runtime_images with a slice of RuntimeImageInput whose length exceeds MAX_RUNTIME_IMAGES (e.g. pasting dozens of screenshots into one turn, or batching all images from a directory into one call).","commonSituations":"A user drags a whole screenshot folder into a session; an automation attaches every chart from a report; a loop that accumulates images without a cap.","solutions":["Split the request: send images across multiple turns/requests, keeping each batch within MAX_RUNTIME_IMAGES.","Pre-select the most relevant images and drop the rest before calling the API.","Raise MAX_RUNTIME_IMAGES only deliberately, since the limit protects the model context and payload size.","In UI code, disable further attachments once the limit is reached and show a counter."],"exampleFix":"// before\nblocks = prepare_runtime_images(&all_30_images)?;\n// after\nfor batch in all_30_images.chunks(MAX_RUNTIME_IMAGES) {\n    blocks.extend(prepare_runtime_images(batch)?);\n}","handlingStrategy":"validation","validationCode":"if images.len() > MAX_RUNTIME_IMAGES {\n    return Err(anyhow!(\"too many images: {} > {}\", images.len(), MAX_RUNTIME_IMAGES));\n}","typeGuard":null,"tryCatchPattern":"match prepare_runtime_images(&images) {\n    Err(e) if e.to_string().contains(\"attachment limit\") => {\n        eprintln!(\"send at most {} images per request\", MAX_RUNTIME_IMAGES); }\n    other => other?,\n}","preventionTips":["Cap the attachment queue in the UI at MAX_RUNTIME_IMAGES","Batch images across turns instead of one request","Summarize excess images in text rather than attaching all"],"tags":["image","limit","validation"],"backgroundTag":"payload-too-large","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}