gchq/CyberChef · error · OperationError

Invalid number of rounds: ${rounds} Rounds must be an integ

Error message

Invalid number of rounds: ${rounds}

Rounds must be an integer between 1 and 255. Standard XTEA uses 32 rounds.

What it means

Thrown by XTEAEncrypt.run when rounds (args[6]) is not an integer in 1–255. Same bounds as decrypt; standard XTEA uses 32 rounds and you must use the same count on both sides.

Source

Thrown at src/core/operations/XTEAEncrypt.mjs:96

    run(input, args) {
        const key = Utils.convertToByteArray(args[0].string, args[0].option),
            iv = Utils.convertToByteArray(args[1].string, args[1].option),
            [,, mode, inputType, outputType, padding, rounds] = args;

        if (key.length !== 16)
            throw new OperationError(`Invalid key length: ${key.length} bytes

XTEA requires a key length of 16 bytes (128 bits).
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);

        if (iv.length !== TEA_BLOCK_SIZE && iv.length !== 0 && mode !== "ECB")
            throw new OperationError(`Invalid IV length: ${iv.length} bytes

XTEA uses an IV length of ${TEA_BLOCK_SIZE} bytes (${TEA_BLOCK_SIZE * 8} bits).
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);

        if (!Number.isInteger(rounds) || rounds < 1 || rounds > 255)
            throw new OperationError(`Invalid number of rounds: ${rounds}

Rounds must be an integer between 1 and 255. Standard XTEA uses 32 rounds.`);

        // Default IV to null bytes if empty (like AES)
        const actualIv = iv.length === 0 ? new Array(TEA_BLOCK_SIZE).fill(0) : iv;

        input = Utils.convertToByteArray(input, inputType);
        const output = encryptXTEA(input, key, actualIv, mode, padding, rounds);
        return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
    }

}

export default XTEAEncrypt;

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Set rounds to the intended integer (32 for standard XTEA).
  2. Pass rounds as a number, not a string, within 1–255.
  3. Record the count used for encryption and reuse it for decryption.

Example fix

// before
args:[key, iv, "CBC", "Hex", "Hex", "PKCS5", "32"]
// after
args:[key, iv, "CBC", "Hex", "Hex", "PKCS5", 32]
Defensive patterns

Strategy: validation

Validate before calling

function xteaRoundsArg(rounds) {
  if (!Number.isInteger(rounds) || rounds < 1 || rounds > 255) throw new Error("rounds must be an integer 1..255");
  return rounds;
}

Type guard

const isValidXteaRounds = (r) => Number.isInteger(r) && r >= 1 && r <= 255;

Try / catch

try { chef.bake(data, recipe); } catch (e) { if (/Invalid number of rounds/.test(e.message)) { /* set rounds=32 */ } else throw e; }

Prevention

When it happens

Trigger: rounds is fractional, NaN, out of range, or a string. Remember: a valid-but-wrong integer does not throw, it just produces ciphertext that won't decrypt with a different count.

Common situations: Non-standard round counts set manually; recipe JSON serialising rounds as a string; disagreement between encrypt and decrypt counts.

Related errors


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