{"record":{"id":"37a58b9d6ef63358","repo":"pbakaus/impeccable","slug":"embed-prompt-malformed-png","errorCode":null,"errorMessage":"embed-prompt: malformed PNG\n","messagePattern":"embed-prompt: malformed PNG\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/context/src/embed_prompt.rs","lineNumber":287,"sourceCode":"                        return 1;\n                    }\n                },\n                _ => None,\n            },\n        };\n        let Some(prompt) = prompt.filter(|p| !p.is_empty()) else {\n            io.err(\"embed-prompt: --prompt or --prompt-file required\\n\");\n            return 1;\n        };\n        let plen = utf16_len(&prompt);\n        if png {\n            // JS-PARITY: embed-prompt.mjs#641 finds IEND by walking the PNG\n            // chunks (not buf.indexOf('IEND')) and reuses parsePng's chunk list\n            // and prompt to rebuild the body idempotently.\n            let (chunks, existing) = parse_png(&buf);\n            let iend: i64 = chunks.iter().find(|c| &c.ty == b\"IEND\").map(|c| c.offset as i64).unwrap_or(-1);\n            if iend < 8 {\n                io.err(\"embed-prompt: malformed PNG\\n\");\n                return 1;\n            }\n            let iend = iend as usize;\n            let mut text_data = KEYWORD.to_vec();\n            text_data.push(0);\n            text_data.extend_from_slice(prompt.as_bytes());\n            let text_chunk = png_chunk(b\"tEXt\", &text_data);\n            let out: Vec<u8> = if existing.is_some() {\n                let mut body: Vec<u8> = Vec::new();\n                for c in &chunks {\n                    if c.offset < iend && !c.prompt_chunk {\n                        body.extend_from_slice(&buf[c.offset..c.end]);\n                    }\n                }\n                let mut o = buf[..8].to_vec();\n                o.extend_from_slice(&body);\n                o.extend_from_slice(&text_chunk);\n                o.extend_from_slice(&png_chunk(b\"IEND\", &[]));","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/pbakaus/impeccable/blob/2bc2879276c1f321a53c4ca99d3371e411329b52/crates/context/src/embed_prompt.rs#L269-L305","documentation":"When embedding into a PNG, the CLI parses the chunk list to locate the IEND chunk and rebuild the file idempotently. If no valid IEND chunk offset is found (iend < 8), the file is not a structurally valid PNG and the CLI exits 1 with this message.","triggerScenarios":"Running `embed-prompt --image <file> --prompt ...` where the file has a .png-ish path/type but is truncated, corrupt, or not actually a PNG (wrong magic bytes or chopped trailing IEND).","commonSituations":"Partially downloaded/truncated PNGs, files renamed to .png without conversion, images mangled by a prior tool, or passing a JPEG with a .png extension.","solutions":["Verify the file is a valid PNG (file out.png should say 'PNG image data' and end with IEND).","Re-export or regenerate the image; do not hand-edit PNG bytes.","Confirm the image-producing step completed before embedding."],"exampleFix":"// before\nimpeccable embed-prompt --image truncated.png --prompt \"x\"\n// after\nfile truncated.png  # confirm 'PNG image data'\nimpeccable embed-prompt --image valid.png --prompt \"x\"","handlingStrategy":"validation","validationCode":"const head = fs.readFileSync(f).subarray(0,8); const isPng = head.equals(Buffer.from([0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a]));","typeGuard":"const isPng = (buf) => buf.length > 8 && buf.subarray(0,8).equals(Buffer.from([0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A]));","tryCatchPattern":"try { embedPrompt(img, prompt); } catch (e) { if (/malformed PNG/.test(e.message)) { console.error('re-export the image; it is truncated or not a real PNG'); } throw e; }","preventionTips":["Verify images with `file` before embedding","Never truncate or hand-edit PNG bytes","Confirm the generating step wrote a complete file"],"tags":["cli","png","corrupt-file","validation"],"backgroundTag":"malformed-png-data","analyzedSha":"2bc2879276c1f321a53c4ca99d3371e411329b52","analyzedAt":"2026-09-08T04:51:14.109Z","contentChangedAt":"2026-09-08T04:51:14.109Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}