gchq/CyberChef · error · OperationError

Number of bytes is not a divisor of ${bytesPerPixel}

Error message

Number of bytes is not a divisor of ${bytesPerPixel}

What it means

Thrown by GenerateImage when the input byte length is not evenly divisible by the bytes-per-pixel for the chosen mode. For RGB (3) the input length must be a multiple of 3; for RGBA (4) a multiple of 4, etc. This ensures every pixel is fully populated. The Bits mode (1/8 bytes/pixel) is skipped because bytesPerPixel is fractional (not > 0 is false for 1/8... actually 1/8 > 0 is true, so fractional modulo applies).

Source

Thrown at src/core/operations/GenerateImage.mjs:90

        const [mode, scale, width] = args;
        input = new Uint8Array(input);

        const bytePerPixelMap = {
            Greyscale: 1,
            RG: 2,
            RGB: 3,
            RGBA: 4,
            Bits: 1 / 8,
        };

        if (!Object.hasOwn(bytePerPixelMap, mode)) {
            throw new OperationError(`Unsupported Mode: (${mode})`);
        }

        const bytesPerPixel = bytePerPixelMap[mode];

        if (bytesPerPixel > 0 && input.length % bytesPerPixel !== 0) {
            throw new OperationError(
                `Number of bytes is not a divisor of ${bytesPerPixel}`,
            );
        }

        const height = Math.ceil(input.length / bytesPerPixel / width);
        const image = new Jimp({ width, height });

        if (isWorkerEnvironment())
            self.sendStatusMessage("Generating image from data...");

        if (mode === "Bits") {
            let index = 0;
            for (let j = 0; j < input.length; j++) {
                const curByte = Utils.bin(input[j]);
                for (let k = 0; k < 8; k++, index++) {
                    const x = index % width;
                    const y = Math.floor(index / width);

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Pad or truncate the input so its byte length is a multiple of bytesPerPixel (1 for Greyscale/RG-ish, 2 for RG, 3 for RGB, 4 for RGBA).
  2. Switch to Greyscale mode if you want every byte to map to a pixel.
  3. Use Bits mode for bit-level packing, but ensure the length works with the fractional divisor.

Example fix

// before: RGB mode, 100 bytes
input = buf(100); // 100 % 3 !== 0 -> error
// after: trim to nearest multiple of 3
input = buf(99);
Defensive patterns

Strategy: validation

Validate before calling

const BPP = { Greyscale: 1, RG: 2, RGB: 3, RGBA: 4 };
const bpp = BPP[mode];
if (bpp && input.length % bpp !== 0) {
  // pad or truncate input to a multiple of bpp before calling the operation
}

Prevention

When it happens

Trigger: Selecting RGB mode with 100 bytes of input (100 % 3 !== 0), or RGBA mode with a length that is not a multiple of 4. For Bits mode, the fractional check against 0.125 can also trigger for odd-length input because of floating-point modulo.

Common situations: Feeding raw binary data of arbitrary length without padding/truncating to the pixel boundary, or switching modes without adjusting input length.

Related errors


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