pbakaus/impeccable · error

embed-prompt: malformed PNG

Error message

embed-prompt: malformed PNG

What it means

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.

Source

Thrown at crates/context/src/embed_prompt.rs:287

                        return 1;
                    }
                },
                _ => None,
            },
        };
        let Some(prompt) = prompt.filter(|p| !p.is_empty()) else {
            io.err("embed-prompt: --prompt or --prompt-file required\n");
            return 1;
        };
        let plen = utf16_len(&prompt);
        if png {
            // JS-PARITY: embed-prompt.mjs#641 finds IEND by walking the PNG
            // chunks (not buf.indexOf('IEND')) and reuses parsePng's chunk list
            // and prompt to rebuild the body idempotently.
            let (chunks, existing) = parse_png(&buf);
            let iend: i64 = chunks.iter().find(|c| &c.ty == b"IEND").map(|c| c.offset as i64).unwrap_or(-1);
            if iend < 8 {
                io.err("embed-prompt: malformed PNG\n");
                return 1;
            }
            let iend = iend as usize;
            let mut text_data = KEYWORD.to_vec();
            text_data.push(0);
            text_data.extend_from_slice(prompt.as_bytes());
            let text_chunk = png_chunk(b"tEXt", &text_data);
            let out: Vec<u8> = if existing.is_some() {
                let mut body: Vec<u8> = Vec::new();
                for c in &chunks {
                    if c.offset < iend && !c.prompt_chunk {
                        body.extend_from_slice(&buf[c.offset..c.end]);
                    }
                }
                let mut o = buf[..8].to_vec();
                o.extend_from_slice(&body);
                o.extend_from_slice(&text_chunk);
                o.extend_from_slice(&png_chunk(b"IEND", &[]));

View on GitHub (pinned to 2bc2879276)

Solutions

  1. Verify the file is a valid PNG (file out.png should say 'PNG image data' and end with IEND).
  2. Re-export or regenerate the image; do not hand-edit PNG bytes.
  3. Confirm the image-producing step completed before embedding.

Example fix

// before
impeccable embed-prompt --image truncated.png --prompt "x"
// after
file truncated.png  # confirm 'PNG image data'
impeccable embed-prompt --image valid.png --prompt "x"
Defensive patterns

Strategy: validation

Validate before calling

const head = fs.readFileSync(f).subarray(0,8); const isPng = head.equals(Buffer.from([0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a]));

Type guard

const isPng = (buf) => buf.length > 8 && buf.subarray(0,8).equals(Buffer.from([0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A]));

Try / catch

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; }

Prevention

When it happens

Trigger: 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).

Common situations: Partially downloaded/truncated PNGs, files renamed to .png without conversion, images mangled by a prior tool, or passing a JPEG with a .png extension.

Understand the failure class

Related errors


AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08). Data as JSON: /api/errors/37a58b9d6ef63358. Report an issue: GitHub.