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

  1. Compress or resize the image before encoding so its base64 fits the limit.
  2. Convert to JPEG with reasonable quality — typically the biggest win for photos.
  3. Check data_base64.len() against the limit in the caller and downsize large images first.
  4. 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

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


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)