gchq/CyberChef · error · OperationError
Error loading image. (${err})
Error message
Error loading image. (${err}) What it means
Thrown from the catch block wrapping Jimp.read(input) in DitherImage.run. CyberChef first passes the input through isImage() (a magic-byte sniff), which only checks a file signature and does not validate structural integrity. Jimp.read then fully decodes the bytes, and when decoding fails the underlying Jimp/js-binary-parser error is re-thrown as an OperationError 'Error loading image. (${err})'. The placeholder interpolates Jimp's own message, which usually names the codec that failed (PNG/JPEG/BMP/etc.).
Source
Thrown at src/core/operations/DitherImage.mjs:48
this.presentType = "html";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {byteArray}
*/
async run(input, args) {
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})`);
}
try {
if (isWorkerEnvironment())
self.sendStatusMessage("Applying dither to image...");
image.dither();
let imageBuffer;
if (image.mime === "image/gif") {
imageBuffer = await image.getBuffer(JimpMime.png);
} else {
imageBuffer = await image.getBuffer(image.mime);
}
return imageBuffer.buffer;
} catch (err) {
throw new OperationError(
`Error applying dither to image. (${err})`,
);
}View on GitHub (pinned to 4290ea7539)
Solutions
- Verify the input decodes in an external viewer before feeding DitherImage; if not, fix the source upstream.
- If bytes come from a previous operation, inspect that step's output (add Hex dump / Render image) to confirm the body survived.
- Ensure the input is one of the formats Jimp decodes (PNG, JPEG, BMP, GIF, TIFF) rather than trusting the magic-byte sniff.
- Re-encode the source image to PNG with an external tool and retry.
Example fix
// before: bytes that only share a header run(corruptedBytes, []); // after: structurally valid PNG run(await reencodeToPng(originalBytes), []);
Defensive patterns
Strategy: validation
Validate before calling
// Validate the image decodes fully before DitherImage.
import Jimp from "jimp";
async function isDecodableImage(bytes) {
try { await Jimp.read(Buffer.from(bytes)); return true; }
catch { return false; }
}
if (!(await isDecodableImage(input))) throw new Error("input is not a decodable image"); Try / catch
try {
const out = await dither.run(input, args);
} catch (e) {
if (String(e).includes("Error loading image")) { /* bad input - do not retry */ }
else throw e;
} Prevention
- Sniff magic bytes AND attempt a full decode in a pre-validation step before image operations.
- Avoid chaining byte-mutating operations immediately before DitherImage.
- Reject zero-length or header-only inputs before they reach Jimp.read.
When it happens
Trigger: Input passes isImage() because its magic bytes match a recognised image signature, but the file is truncated, corrupted, or has a valid header with malformed pixel data. Also a non-image sharing an image magic number, a zero-length body after a valid header, or a format Jimp's bundled decoders cannot parse (e.g. some TIFF/HEIF variants) reaches Jimp.read and throws.
Common situations: Pasting a base64 image whose payload was clipped; a progressive JPEG cut mid-scan; chaining an operation that mutates bytes before DitherImage so the signature survives but the body does not; a very new/obscure container that shares PNG/JPEG magic but is outside Jimp's supported set.
Related errors
- Invalid file type.
- Invalid file format.
- Invalid file type.
- Invalid file type.
- Error applying dither to image. (${err})
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/9b324bf581a7bb72.
Report an issue: GitHub.