{"record":{"id":"1929f1a08ae5042d","repo":"gchq/CyberChef","slug":"error-applying-dither-to-image-err","errorCode":null,"errorMessage":"Error applying dither to image. (${err})","messagePattern":"Error applying dither to image\\. \\((.+?)\\)","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/DitherImage.mjs","lineNumber":63,"sourceCode":"        try {\n            image = await Jimp.read(input);\n        } catch (err) {\n            throw new OperationError(`Error loading image. (${err})`);\n        }\n        try {\n            if (isWorkerEnvironment())\n                self.sendStatusMessage(\"Applying dither to image...\");\n            image.dither();\n\n            let imageBuffer;\n            if (image.mime === \"image/gif\") {\n                imageBuffer = await image.getBuffer(JimpMime.png);\n            } else {\n                imageBuffer = await image.getBuffer(image.mime);\n            }\n            return imageBuffer.buffer;\n        } catch (err) {\n            throw new OperationError(\n                `Error applying dither to image. (${err})`,\n            );\n        }\n    }\n\n    /**\n     * Displays the dithered image using HTML for web apps\n     * @param {ArrayBuffer} data\n     * @returns {html}\n     */\n    present(data) {\n        if (!data.byteLength) return \"\";\n        const dataArray = new Uint8Array(data);\n\n        const type = isImage(dataArray);\n        if (!type) {\n            throw new OperationError(\"Invalid file type.\");\n        }","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/DitherImage.mjs#L45-L81","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the interpolated (${err}) text to identify the failing step (dither vs encode).","If the failure is encoding, pre-convert the source to plain PNG/JPEG so the GIF branch is avoided.","Try a different source image to rule out a Jimp bug tied to specific dimensions/colour depth.","Pin or upgrade Jimp if a regression is suspected and re-run."],"exampleFix":"// before: palette GIF triggering the GIF->PNG branch failure\nrun(gifBytes, []);\n// after: pre-convert to PNG so the generic getBuffer(image.mime) path runs\nrun(await toPng(gifBytes), []);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const out = await dither.run(input, args);\n} catch (e) {\n  if (String(e).includes(\"Error applying dither\")) {\n    // dither/encode failed - try re-encoding source to PNG and retry once\n  } else throw e;\n}","preventionTips":["Pre-convert palette/GIF sources to PNG so the generic getBuffer(image.mime) path is used.","Read the interpolated underlying error to distinguish dither vs encode failure before retrying.","Pin a known-good Jimp version to avoid dither/getBuffer regressions."],"tags":["image-processing","jimp","encoding","operation-error"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}