gchq/CyberChef · error · OperationError

Error applying dither to image. (${err})

Error message

Error applying dither to image. (${err})

What it means

Thrown from the second try/catch in DitherImage.run wrapping image.dither() and the subsequent getBuffer encoding. After Jimp loaded the image, this block runs the Floyd-Steinberg dither and re-encodes the result. Any failure here (Jimp internal error, an unsupported mime on the decoded buffer, or getBuffer rejecting) is wrapped as 'Error applying dither to image. (${err})' with the underlying cause interpolated.

Source

Thrown at src/core/operations/DitherImage.mjs:63

        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})`,
            );
        }
    }

    /**
     * Displays the dithered image using HTML for web apps
     * @param {ArrayBuffer} data
     * @returns {html}
     */
    present(data) {
        if (!data.byteLength) return "";
        const dataArray = new Uint8Array(data);

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

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Read the interpolated (${err}) text to identify the failing step (dither vs encode).
  2. If the failure is encoding, pre-convert the source to plain PNG/JPEG so the GIF branch is avoided.
  3. Try a different source image to rule out a Jimp bug tied to specific dimensions/colour depth.
  4. Pin or upgrade Jimp if a regression is suspected and re-run.

Example fix

// before: palette GIF triggering the GIF->PNG branch failure
run(gifBytes, []);
// after: pre-convert to PNG so the generic getBuffer(image.mime) path runs
run(await toPng(gifBytes), []);
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const out = await dither.run(input, args);
} catch (e) {
  if (String(e).includes("Error applying dither")) {
    // dither/encode failed - try re-encoding source to PNG and retry once
  } else throw e;
}

Prevention

When it happens

Trigger: Jimp loaded the image but image.dither() throws on an unexpected colour mode/bit depth; image.mime resolves to a value getBuffer cannot produce; or the GIF-to-PNG branch (image.mime === 'image/gif' forcing getBuffer(JimpMime.png)) fails because the PNG encoder rejects the dithered bitmap state.

Common situations: A palette/GIF image whose internal mode is incompatible with Jimp's dither routine; a Jimp version regression changing dither/getBuffer behaviour; an exotic colour profile that dither() mishandles.

Related errors


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