gchq/CyberChef · warning · OperationError

Could not read a QR code from the image.

Error message

Could not read a QR code from the image.

What it means

Thrown by parseQrCode when jsQR returns null — the image was decoded and normalised but no QR code could be located or decoded in it. There is no underlying error object; it is a deterministic 'not found' result.

Source

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

        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,
        image.height,
    );
    if (qrData) {
        return qrData.data;
    } else {
        throw new OperationError("Could not read a QR code from the image.");
    }
}

/**
 * Generates a QR code from the input string
 *
 * @param {string} input
 * @param {string} format
 * @param {number} moduleSize
 * @param {number} margin
 * @param {string} errorCorrection
 * @returns {ArrayBuffer}
 */
export function generateQrCode(
    input,
    format,
    moduleSize,
    margin,

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Provide a higher-resolution, well-lit, front-on capture with a clean quiet zone.
  2. Try normalise=false (sometimes auto-normalise hurts low-contrast codes).
  3. Pre-process: upscale, binarise, deskew, or increase contrast before parsing.
Defensive patterns

Strategy: fallback

Validate before calling

async function decodeQrBestEffort(input) {
  for (const norm of [true, false]) {
    try { return await parseQrCode(input, norm); } catch (e) { last = e; }
  }
  throw last;
}

Try / catch

try {
  return await parseQrCode(input, normalise);
} catch (e) {
  if (e instanceof OperationError && /Could not read a QR code/.test(e.message)) {
    // try alternate preprocessing: upscale/deskew/binarise the image
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling parseQrCode on an image with no QR code, a QR too small/blurry/skewed for jsQR, low contrast after normalisation, partial occlusion, inverted colours, or a damaged quiet zone.

Common situations: Photo of a QR with glare/shadow/perspective distortion; screenshot scaled below module resolution; rotated QR; QR against a noisy background; wrong image passed.

Related errors


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