jgraph/drawio-desktop · error · Error
PNGImageDecoder1
Error message
PNGImageDecoder1
What it means
Thrown by the catch block guarding the PNG signature read in writePngWithText (src/main/electron.js:1971-1992). The inner try reads the first 8 bytes of origBuff and validates the PNG magic (0x89504e47 / 0x0d0a1a0a, throwing the sentinel 'PNGImageDecoder0' on mismatch); any failure there — short buffer, non-Buffer, or bad magic — is logged via log.error and re-thrown as the opaque 'PNGImageDecoder1'. This is the only entry point that embeds dpi or mxGraphModel XML into an exported PNG (lines 2746, 2753).
Source
Thrown at src/main/electron.js:1991
var magic1 = origBuff.readUInt32BE(inOffset);
inOffset += 4;
var magic2 = origBuff.readUInt32BE(inOffset);
inOffset += 4;
if (magic1 != 0x89504e47 && magic2 != 0x0d0a1a0a)
{
throw new Error("PNGImageDecoder0");
}
outBuff.writeUInt32BE(magic1, outOffset);
outOffset += 4;
outBuff.writeUInt32BE(magic2, outOffset);
outOffset += 4;
}
catch (e)
{
log.error(e.message, {stack: e.stack});
throw new Error("PNGImageDecoder1");
}
try
{
while (inOffset < origBuff.length)
{
var length = origBuff.readInt32BE(inOffset);
inOffset += 4;
var type = origBuff.readInt32BE(inOffset)
inOffset += 4;
if (type == PNG_CHUNK_IDAT)
{
// Insert zTXt chunk before IDAT chunk
outBuff.writeInt32BE(dataLen, outOffset);
outOffset += 4;
var typeSignature = isDpi? 'pHYs' : (compressed ? "zTXt" : "tEXt");View on GitHub (pinned to 403a2cb79f)
Solutions
- Confirm the buffer passed to writePngWithText starts with the PNG signature 89 50 4E 47 0D 0A 1A 0A before calling it.
- If invoking through the export IPC, verify args.format==='png' and that nativeImage.toPNG() returned a non-empty Buffer (check buf.length >= 8).
- On Linux CI/container builds, install the Electron runtime dependencies (libpng, libgtk, etc.) so nativeImage rendering produces a real PNG.
- Inspect the log.error line emitted just before the throw — it carries the original error message and stack pinpointing the real cause.
Example fix
// before
var data = img.toPNG();
data = writePngWithText(data, 'dpi', args.dpi);
// after
var data = img.toPNG();
if (!Buffer.isBuffer(data) || data.length < 8 ||
data.readUInt32BE(0) !== 0x89504e47 || data.readUInt32BE(4) !== 0x0d0a1a0a) {
throw new Error('PNG export produced an invalid PNG buffer');
}
data = writePngWithText(data, 'dpi', args.dpi); Defensive patterns
Strategy: validation
Validate before calling
function isValidPng(buf) {
return Buffer.isBuffer(buf) && buf.length >= 8 &&
buf.readUInt32BE(0) === 0x89504e47 &&
buf.readUInt32BE(4) === 0x0d0a1a0a;
}
// usage
if (!isValidPng(data)) throw new Error('not a PNG');
writePngWithText(data, 'dpi', args.dpi); Type guard
function isValidPng(buf) {
return Buffer.isBuffer(buf) && buf.length >= 8 &&
buf.readUInt32BE(0) === 0x89504e47 &&
buf.readUInt32BE(4) === 0x0d0a1a0a;
} Try / catch
try { writePngWithText(data, 'dpi', args.dpi); }
catch (e) {
if (e.message === 'PNGImageDecoder1') {
log.error('PNG embed failed; falling back to unmodified PNG', data && data.length);
return data; // degrade to plain PNG
}
throw e;
} Prevention
- Always validate the PNG signature before calling writePngWithText.
- On Linux/container Electron, install nativeImage runtime deps so toPNG() returns real bytes.
- Inspect log.error output — it carries the original inner error before the opaque PNGImageDecoder1 re-throw.
When it happens
Trigger: Export to PNG with args.dpi set, or args.embedXml=="1" with an mxGraphModel payload, when img.toPNG() returned a buffer that is not a valid 8-byte PNG (truncated, JPEG/PNG mismatch, nativeImage fallback to empty buffer on a headless/minimal Electron build).
Common situations: Running image export in an environment where nativeImage produced no real PNG (missing libpng, headless Linux without the right Electron deps); a custom caller passing a pre-encoded non-PNG buffer into writePngWithText; a regression where args.format was 'png' but toPNG() silently returned empty.
AI-assisted analysis of jgraph/drawio-desktop@403a2cb79f (2026-08-13).
Data as JSON: /api/errors/aa8f930dd04b0e5b.
Report an issue: GitHub.