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

  1. Set both a and b to non-negative integers (e.g. a=5, b=8).
  2. 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.
  3. 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

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


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