gchq/CyberChef · error · OperationError

Byte length must be a positive integer

Error message

Byte length must be a positive integer

What it means

Thrown by fromHex when the byteLen argument fails the positivity/integer guard (`byteLen < 1 || Math.round(byteLen) !== byteLen`). byteLen controls how many hex digits are grouped into each output byte (default 2). Zero, negative, fractional, or NaN values are rejected. This is an OperationError, so recipe execution treats it as expected output.

Source

Thrown at src/core/lib/Hex.mjs:105

/**
 * Convert a hex string into a byte array.
 *
 * @param {string} data
 * @param {string} [delim]
 * @param {number} [byteLen=2]
 * @returns {byteArray}
 *
 * @example
 * // returns [10,20,30]
 * fromHex("0a 14 1e");
 *
 * // returns [10,20,30]
 * fromHex("0a:14:1e", "Colon");
 */
export function fromHex(data, delim="Auto", byteLen=2) {
    if (byteLen < 1 || Math.round(byteLen) !== byteLen)
        throw new OperationError("Byte length must be a positive integer");

    if (delim !== "None") {
        const delimRegex = delim === "Auto" ? /[^a-f\d]|0x/gi : Utils.regexRep(delim);
        data = data.split(delimRegex);
    } else {
        data = [data];
    }

    const output = [];
    for (let i = 0; i < data.length; i++) {
        for (let j = 0; j < data[i].length; j += byteLen) {
            output.push(parseInt(data[i].substr(j, byteLen), 16));
        }
    }
    return output;
}

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Pass a positive integer byteLen (the typical value is 2).
  2. Validate byteLen is a positive integer before invoking fromHex.
  3. Default the argument explicitly when sourcing it from untrusted UI input.

Example fix

// before
fromHex(hexStr, "Space", 0);

// after
fromHex(hexStr, "Space", 2);
Defensive patterns

Strategy: validation

Validate before calling

function fromHexSafe(data, delim = "Auto", byteLen = 2) {
  if (!Number.isInteger(byteLen) || byteLen < 1) {
    throw new Error("byteLen must be a positive integer");
  }
  return fromHex(data, delim, byteLen);
}

Type guard

const isPositiveInt = n => Number.isInteger(n) && n >= 1;

Try / catch

try {
  fromHex(data, delim, byteLen);
} catch (err) {
  if (err instanceof OperationError && /Byte length must be a positive integer/.test(err.message)) {
    // fix the byteLen argument (default to 2) and retry
  } else throw err;
}

Prevention

When it happens

Trigger: Calling `fromHex(data, delim, 0)`, `fromHex(data, delim, -1)`, `fromHex(data, delim, 2.5)`, or passing a value that coerces to NaN. Also triggered by a recipe/UI supplying an out-of-range 'Byte length' argument.

Common situations: Misconfigured recipe argument; passing undefined through arithmetic that yields NaN; user typing 0 or a decimal in the Byte length field.

Related errors


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