gchq/CyberChef · warning · OperationError

Error normalising image. (${err})

Error message

Error normalising image. (${err})

What it means

Thrown by parseQrCode when `image.greyscale()` or `image.normalize()` throws after a successful read. The original Jimp error is appended. This is rare and typically indicates an edge case in the decoded bitmap (e.g. unsupported colour space or zero-pixel image).

Source

Thrown at src/core/lib/QRCode.mjs:36

 * @param {ArrayBuffer} input
 * @param {boolean} normalise
 * @returns {string}
 */
export async function parseQrCode(input, normalise) {
    let image;
    try {
        image = await Jimp.read(input);
    } catch (err) {
        throw new OperationError(`Error opening image. (${err})`);
    }

    try {
        if (normalise) {
            image.greyscale();
            image.normalize();
        }
    } catch (err) {
        throw new OperationError(`Error normalising image. (${err})`);
    }

    // Remove transparency which jsQR cannot handle
    image.scan((x, y, idx) => {
        // If pixel is fully transparent, make it opaque white
        if (image.bitmap.data[idx + 3] === 0x00) {
            image.bitmap.data[idx + 0] = 0xff;
            image.bitmap.data[idx + 1] = 0xff;
            image.bitmap.data[idx + 2] = 0xff;
        }
        // Otherwise, make it fully opaque at its existing colour
        image.bitmap.data[idx + 3] = 0xff;
    });
    image = await Jimp.read(await image.getBuffer(JimpMime.jpeg));

    const qrData = jsQR(
        new Uint8ClampedArray(image.bitmap.data),
        image.width,

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Retry with normalise=false to bypass greyscale/normalise.
  2. Re-encode the source image to a standard 8-bit sRGB PNG before parsing.
  3. Check the Jimp version is compatible with this CyberChef build.

Example fix

// before
await parseQrCode(input, true); // throws on degenerate image
// after
await parseQrCode(input, false);
Defensive patterns

Strategy: retry

Validate before calling

async function safeParseQr(input) {
  try { return await parseQrCode(input, true); }
  catch (e) { if (/normalising/.test(e.message)) return await parseQrCode(input, false); throw e; }
}

Try / catch

try {
  return await parseQrCode(input, true);
} catch (e) {
  if (e instanceof OperationError && /normalising/.test(e.message)) {
    return await parseQrCode(input, false); // retry without normalise
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling parseQrCode(input, true) where the image decodes but Jimp's pixel operations fail — degenerate dimensions (0x0), unusual bit depth, or a Jimp version regression.

Common situations: Passing normalise=true with an image Jimp decoded only partially; Jimp/library version mismatch after upgrade; CMYK/16-bit images that Jimp represents oddly.

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/421b2b92dc1cecaf. Report an issue: GitHub.