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
- 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).
- Switch to Greyscale mode if you want every byte to map to a pixel.
- 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
- Pre-size input to an exact multiple of bytesPerPixel for the chosen mode.
- Prefer Greyscale mode when input length is arbitrary.
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
- Invalid file type.
- Invalid file format.
- Invalid file type.
- Invalid file type.
- Could not extract EXIF data from image: ${err}
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/2c232c4c6768e9c9.
Report an issue: GitHub.