gchq/CyberChef · error · OperationError
L must be non-negative
Error message
L must be non-negative
What it means
Thrown by Derive HKDF Key run() when L (the requested output length in octets) is negative. HKDF (RFC 5869) defines L as a non-negative integer; the operation's UI sets min:0 on the number argument, but a programmatic call or a hand-edited recipe can pass a negative value. The guard runs before any HKDF computation.
Source
Thrown at src/core/operations/DeriveHKDFKey.mjs:112
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
run(input, args) {
const argSalt = Utils.convertToByteString(args[0].string || "", args[0].option),
info = Utils.convertToByteString(args[1].string || "", args[1].option),
hashFunc = args[2].toLowerCase(),
extractMode = args[3],
L = args[4],
IKM = Utils.arrayBufferToStr(input, false),
hasher = CryptoApi.getHasher(hashFunc),
HashLen = hasher.finalize().length;
if (L < 0) {
throw new OperationError("L must be non-negative");
}
if (L > 255 * HashLen) {
throw new OperationError("L too large (maximum length for " + args[2] + " is " + (255 * HashLen) + ")");
}
const hmacHash = function(key, data) {
hasher.reset();
const mac = CryptoApi.getHmac(key, hasher);
mac.update(data);
return mac.finalize();
};
const salt = extractMode === "with salt" ? argSalt : "\0".repeat(HashLen);
const PRK = extractMode === "skip" ? IKM : hmacHash(salt, IKM);
let T = "";
let result = "";
for (let i = 1; i <= 255 && result.length < L; i++) {
const TNext = hmacHash(PRK, T + info + String.fromCharCode(i));
result += TNext;View on GitHub (pinned to 4290ea7539)
Solutions
- Set L to a non-negative value (0 returns an empty string, typical KDF lengths are 16/32/64).
- Validate the length upstream before invoking run().
- If the UI allows a negative value to slip through, report it as a UI min-enforcement bug; meanwhile clamp to 0.
Example fix
// before const args = [salt, info, "SHA256", "with salt", -16]; op.run(input, args); // throws // after const args = [salt, info, "SHA256", "with salt", 16]; op.run(input, args);
Defensive patterns
Strategy: validation
Validate before calling
function isValidHkdfLength(L) {
return Number.isInteger(L) && L >= 0;
} Type guard
/** @returns {boolean} */
function isNonNegativeInt(L) {
return Number.isInteger(L) && L >= 0;
} Try / catch
try {
out = deriveHkdfKey.run(input, args);
} catch (e) {
if (e instanceof OperationError && /L must be non-negative/.test(e.message)) {
args[4] = Math.max(0, Math.floor(args[4]));
out = deriveHkdfKey.run(input, args);
} else throw e;
} Prevention
- Clamp L to a non-negative integer before invoking.
- Validate numeric operation args when building recipes dynamically.
- Prefer typical KDF lengths (16/32/64) unless more material is genuinely needed.
When it happens
Trigger: Passing args[4] < 0 to run(). Possible via programmatic invocation, an imported recipe with a bad number, or a UI bug that allows a negative number through despite min:0.
Common situations: Automation/Node-API passing an unvalidated length; a recipe file with a corrupted L value; chaining an operation whose numeric output can be negative into this op's L argument.
Related errors
- L too large (maximum length for ${args[2]} is ${255 * HashLe
- Invalid IV length: ${iv.length} bytes TEA uses an IV length
- Invalid key length: ${key.length} bytes TEA requires a key
- Invalid IV length: ${iv.length} bytes TEA uses an IV length
- Byte length must be a positive integer
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/a9a229669bd69de6.
Report an issue: GitHub.