gchq/CyberChef · error · OperationError
The values of a and b can only be integers.
Error message
The values of a and b can only be integers.
What it means
Thrown by AffineCipherDecode.run when either argument a (multiplicative slope) or b (additive shift) is not a non-negative integer. The regex /^\+?(0|[1-9]\d*)$/ coerces each value to a string and rejects decimals, negative numbers, empty strings, and any non-numeric input before the modular arithmetic runs. Both args are declared as type 'number' in the operation's recipe, so this guards against a number field that was filled with a fractional or out-of-range value.
Source
Thrown at src/core/operations/AffineCipherDecode.mjs:56
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*
* @throws {OperationError} if a or b values are invalid
*/
run(input, args) {
const alphabet = "abcdefghijklmnopqrstuvwxyz",
[a, b] = args,
aModInv = Utils.modInv(a, 26); // Calculates modular inverse of a
let output = "";
if (!/^\+?(0|[1-9]\d*)$/.test(a) || !/^\+?(0|[1-9]\d*)$/.test(b)) {
throw new OperationError("The values of a and b can only be integers.");
}
if (Utils.gcd(a, 26) !== 1) {
throw new OperationError("The value of `a` must be coprime to 26.");
}
for (let i = 0; i < input.length; i++) {
if (alphabet.indexOf(input[i]) >= 0) {
// Uses the affine decode function (y-b * A') % m = x (where m is length of the alphabet and A' is modular inverse)
output += alphabet[Utils.mod((alphabet.indexOf(input[i]) - b) * aModInv, 26)];
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
// Same as above, accounting for uppercase
output += alphabet[Utils.mod((alphabet.indexOf(input[i].toLowerCase()) - b) * aModInv, 26)].toUpperCase();
} else {
// Non-alphabetic characters
output += input[i];
}
}View on GitHub (pinned to 4290ea7539)
Solutions
- Set both a and b to non-negative integers (e.g. a=5, b=8).
- If you need a negative shift, keep b non-negative and use the Affine Cipher Encode direction or transform the math instead of passing a negative b.
- When building the recipe in code, validate with Number.isInteger(v) && v >= 0 before passing the args array.
Example fix
// before
recipe.setArgs([1.5, 8]);
const out = chef.affineCipherDecode("HELLO", [1.5, 8]);
// after
recipe.setArgs([5, 8]); // a=5 is coprime to 26, b=8 shift
const out = chef.affineCipherDecode("HELLO", [5, 8]); Defensive patterns
Strategy: validation
Validate before calling
function assertAffineIntegers(a, b) {
const re = /^\+?(0|[1-9]\d*)$/;
if (!re.test(String(a)) || !re.test(String(b))) {
throw new Error(`a and b must be non-negative integers; got a=${a}, b=${b}`);
}
}
// call before recipe.run()
assertAffineIntegers(a, b); Type guard
function isNonNegIntArg(v) {
return (typeof v === "number" && Number.isInteger(v) && v >= 0)
|| (typeof v === "string" && /^\+?(0|[1-9]\d*)$/.test(v));
} Prevention
- Type the a and b fields as integers in the UI number inputs.
- In code, pass JS numbers that satisfy Number.isInteger(v) && v >= 0.
- Sanitize imported recipe JSON so a/b are integers before execution.
When it happens
Trigger: Passing a fractional value (e.g. a=1.5 or b=2.7), a negative number (e.g. b=-3), NaN, or an empty/non-numeric string for a or b in the recipe arguments. The regex coerces the number to a string, so 1.5 becomes "1.5" which fails to match.
Common situations: User types a decimal into the a or b number field; parameters copied from another tool that used real-valued coefficients; a recipe imported from JSON where the value was serialized as a float; programmatic ChefNode/Recipe construction passing a float.
Related errors
- The value of `a` must be coprime to 26.
- Rotor ${i} must be provided.
- The value of `a` must be coprime to 26.
- The key must consist only of letters in the English alphabet
- 'Drop every' must be a positive integer.
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/8cc05f29dd2dd69a.
Report an issue: GitHub.