{"record":{"id":"c9d85473bf13a4e9","repo":"Hmbown/CodeWhale","slug":"image-has-invalid-base64","errorCode":null,"errorMessage":"image {} has invalid base64","messagePattern":"image (.+?) has invalid base64","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/image_attach.rs","lineNumber":142,"sourceCode":"    images: &[RuntimeImageInput],\n    per_image_limit: usize,\n    total_limit: Option<usize>,\n) -> Result<Vec<ContentBlock>> {\n    let mut total = 0usize;\n    images\n        .iter()\n        .enumerate()\n        .map(|(index, image)| {\n            if image.data_base64.len() > per_image_limit.div_ceil(3) * 4 {\n                bail!(\n                    \"image {} exceeds the {} MiB limit\",\n                    index + 1,\n                    per_image_limit / (1024 * 1024)\n                );\n            }\n            let bytes = STANDARD\n                .decode(&image.data_base64)\n                .map_err(|_| anyhow::anyhow!(\"image {} has invalid base64\", index + 1))?;\n            if bytes.len() > per_image_limit {\n                bail!(\n                    \"image {} exceeds the {} MiB limit\",\n                    index + 1,\n                    per_image_limit / (1024 * 1024)\n                );\n            }\n            total = total.saturating_add(bytes.len());\n            if total_limit.is_some_and(|limit| total > limit) {\n                bail!(\"images exceed the 5 MiB total limit\");\n            }\n            let attached = encode_image_bytes(&bytes, &format!(\"image {}\", index + 1))?;\n            if image.mime != attached.media_type {\n                bail!(\"image {} MIME does not match its content\", index + 1);\n            }\n            decode_and_guard_image(&bytes)?;\n            // Standard padded base64 is the one replay representation.\n            if STANDARD.encode(&bytes) != image.data_base64 {","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/image_attach.rs#L124-L160","documentation":"One of the runtime image inputs carried a data_base64 string that is not valid standard base64, so STANDARD.decode() failed. The error names the 1-based image index so the caller knows which attachment to fix.","triggerScenarios":"prepare_images_with_limit (via prepare_runtime_images or prepare_stored_images) is given a RuntimeImageInput whose data_base64 contains characters outside the standard base64 alphabet, wrong padding, or URL-safe '-_' characters where standard '+/' is required.","commonSituations":"Producers that URL-safe-encode base64; strings with whitespace, newlines, or a `data:` prefix accidentally included in data_base64; copying a base64 string out of JSON tooling that wrapped or escaped it.","solutions":["Re-encode the bytes with standard base64 (with padding) and pass only the payload, stripping any `data:<mime>;base64,` prefix.","If the source uses URL-safe base64, convert '-_' to '+/' and restore padding before assigning data_base64.","Strip whitespace/newlines from the base64 string."],"exampleFix":"// before\ndata_base64: \"iVBORw0KGgoAAAANSUhEUg..._-\" // URL-safe alphabet\n\n// after\ndata_base64: \"iVBORw0KGgoAAAANSUhEUg...+/=\" // standard base64 with padding","handlingStrategy":"validation","validationCode":"fn valid_std_base64(s: &str) -> bool {\n    let cleaned: String = s.chars().filter(|c| !c.is_whitespace()).collect();\n    base64::engine::general_purpose::STANDARD.decode(&cleaned).is_ok()\n}","typeGuard":null,"tryCatchPattern":"// Rust\nmatch STANDARD.decode(&image.data_base64) {\n    Ok(bytes) => attach(bytes),\n    Err(e) => {\n        let repaired = image.data_base64.replace(['-', '_'], \"+/\");\n        attach(STANDARD.decode(repaired.trim())?);\n    }\n}","preventionTips":["Always encode attachments with standard (padded) base64, never URL-safe variants.","Store only the base64 payload in data_base64; keep the mime type in the separate mime field.","Strip whitespace and data-URL prefixes before assigning data_base64."],"tags":["base64","image","validation"],"backgroundTag":"invalid-base64","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"}