gchq/CyberChef · error · OperationError

Error loading image. (${err})

Error message

Error loading image. (${err})

What it means

After isImage() confirms the bytes look like a supported image, Contain Image calls Jimp.read(input) to decode the pixels. If decoding fails — corrupt or truncated payload, a header that matches but a body Jimp cannot parse, or a format this Jimp version lacks a codec for — the thrown error is wrapped as 'Error loading image.' So the magic-byte check passed but the actual decode did not.

Source

Thrown at src/core/operations/ContainImage.mjs:116

        const alignMap = {
            Left: HorizontalAlign.LEFT,
            Center: HorizontalAlign.CENTER,
            Right: HorizontalAlign.RIGHT,
            Top: VerticalAlign.TOP,
            Middle: VerticalAlign.MIDDLE,
            Bottom: VerticalAlign.BOTTOM,
        };

        if (!isImage(input)) {
            throw new OperationError("Invalid file type.");
        }

        let image;
        try {
            image = await Jimp.read(input);
        } catch (err) {
            throw new OperationError(`Error loading image. (${err})`);
        }
        const originalMime = image.mime;
        try {
            if (isWorkerEnvironment())
                self.sendStatusMessage("Containing image...");
            image.contain({
                w: width,
                h: height,
                align: alignMap[hAlign] | alignMap[vAlign],
                mode: resizeMap[alg],
            });

            if (opaqueBg) {
                const newImage = new Jimp({
                    width,
                    height,
                    color: 0x000000ff,
                });

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Re-export or re-save the source image in a standard format (PNG or baseline JPEG) using an image editor.
  2. Verify file integrity (complete download, correct byte length).
  3. Check the Jimp version bundled with this CyberChef build for the supported codec list.
  4. If the format is exotic, transcode it to PNG externally first.

Example fix

// before: truncated PNG (header ok, IDAT missing)
// after: supply the complete, valid PNG file bytes
Defensive patterns

Strategy: try-catch

Validate before calling

import { isImage } from "src/core/lib/FileType.mjs";
// Reduces (not eliminates) the chance: isImage must pass before Jimp.read is attempted.
const bytes = input instanceof ArrayBuffer ? new Uint8Array(input) : input;
if (!isImage(bytes)) {
  throw new Error("Not a recognized image — Jimp.read would likely fail.");
}

Type guard

import { isImage } from "src/core/lib/FileType.mjs";
function isLikelyDecodableImage(buf) {
  const bytes = buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;
  return isImage(bytes) !== false;
}

Try / catch

try {
  result = await containImage.run(input, args);
} catch (err) {
  if (/Error loading image/.test(err.message)) {
    // isImage passed but Jimp decode failed: source is corrupt/truncated or an unsupported sub-format.
    // Re-export the source as PNG/baseline JPEG externally, then retry.
  }
  throw err;
}

Prevention

When it happens

Trigger: Truncated download (header present, body cut off); valid magic bytes but structurally corrupt image; a color space or sub-format Jimp cannot decode (e.g. CMYK JPEG, 16-bit PNG); Jimp version mismatch where isImage detects a type Jimp can't read.

Common situations: Partial file transfer; re-saving from a tool that emitted an exotic variant; dependency upgrade changing Jimp's supported format set; animated/multi-frame containers.

Related errors


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