Hmbown/CodeWhale · error
image exceeds the MiB limit
Error message
image {} exceeds the {} MiB limit What it means
prepare_images_with_limit checks each image's base64 payload length against the per-image limit before decoding; since base64 inflates bytes by 4/3, the pre-decode check uses per_image_limit.div_ceil(3) * 4. This bail fires when the base64 string itself is already too long for the configured per-image MiB budget.
Solutions
- Compress or resize the image before encoding so its base64 fits the limit.
- Convert to JPEG with reasonable quality — typically the biggest win for photos.
- Check data_base64.len() against the limit in the caller and downsize large images first.
- Document the byte cap where images enter the system so oversized ones are rejected earlier with a better message.
Example fix
// before
let b64 = STANDARD.encode(&huge_png_bytes); // > 4/3 * 5MiB
attach(RuntimeImageInput { data_base64: b64, .. })?;
// after
let small = resize_to_max_side(&huge_png_bytes, 2048)?;
attach(RuntimeImageInput { data_base64: STANDARD.encode(&small), .. })?; Defensive patterns
Strategy: validation
Validate before calling
fn b64_fits(data_base64: &str, per_image_limit: usize) -> bool {
data_base64.len() <= per_image_limit.div_ceil(3) * 4
} Try / catch
match prepare_runtime_images(&images) {
Err(e) if e.to_string().contains("MiB limit") => {
eprintln!("shrink images to <= {} MiB each before attaching", MAX_RUNTIME_IMAGE_BYTES / (1024*1024)); }
other => other?,
} Prevention
- Check base64 length before calling the attach API
- Resize/compress large images at ingestion
- Prefer JPEG for photos to stay well under the cap
When it happens
Trigger: Calling prepare_runtime_images or prepare_stored_images with an image whose data_base64 length exceeds per_image_limit.div_ceil(3)*4 — e.g. a >5 MiB (or per-limit) image supplied as base64, caught before any decode work.
Common situations: Attaching a raw camera photo or high-res screenshot that exceeds the MiB cap; reading a large file and base64-encoding it without size checks; a caller passing base64 from another (larger-limit) system.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
- image base64 is not canonical
- image has invalid base64
- images exceed the 5 MiB total limit
- images exceed the attachment limit
- invalid tool image evidence
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/b84e15764740fd32.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/image_attach.rs:134
/// Network callers must first pass `prepare_runtime_images` (4 MiB per image,
/// 10 images and 5 MiB total). Local history never had those aggregate/count
/// limits; impose only its existing per-image bound and bounded full decode.
pub(crate) fn prepare_stored_images(images: &[RuntimeImageInput]) -> Result<Vec<ContentBlock>> {
prepare_images_with_limit(images, MAX_IMAGE_BYTES, None)
}
fn prepare_images_with_limit(
images: &[RuntimeImageInput],
per_image_limit: usize,
total_limit: Option<usize>,
) -> Result<Vec<ContentBlock>> {
let mut total = 0usize;
images
.iter()
.enumerate()
.map(|(index, image)| {
if image.data_base64.len() > per_image_limit.div_ceil(3) * 4 {
bail!(
"image {} exceeds the {} MiB limit",
index + 1,
per_image_limit / (1024 * 1024)
);
}
let bytes = STANDARD
.decode(&image.data_base64)
.map_err(|_| anyhow::anyhow!("image {} has invalid base64", index + 1))?;
if bytes.len() > per_image_limit {
bail!(
"image {} exceeds the {} MiB limit",
index + 1,
per_image_limit / (1024 * 1024)
);
}
total = total.saturating_add(bytes.len());
if total_limit.is_some_and(|limit| total > limit) {
bail!("images exceed the 5 MiB total limit");View on GitHub (pinned to 73e0f67d83)