gchq/CyberChef · error · Error

Invalid recipe

Error message

Invalid recipe

What it means

Thrown by Utils._validatePrettyRecipe() (line 1056), the structural pre-check for the bespoke 'pretty' recipe format (Op_name(args)/disabled). Fires when indexOf('(') returns -1 (no opening paren anywhere from position i) OR when the next '(' sits exactly at position i (no operation name before the paren). Reached only for non-JSON recipes (strings not starting with '[').

Source

Thrown at src/core/Utils.mjs:1056

            recipeConfig.push(op);
        }
        return recipeConfig;
    }


    /**
     * Performs a linear structural validation pass over pretty recipe syntax.
     *
     * @param {string} recipe
     * @throws {Error} if the recipe is structurally invalid
     */
    static _validatePrettyRecipe(recipe) {
        let i = 0;

        while (i < recipe.length) {
            const openParen = recipe.indexOf("(", i);
            if (openParen === -1 || openParen === i) {
                throw new Error("Invalid recipe");
            }

            i = openParen + 1;
            let inString = false,
                escaped = false,
                foundCloseParen = false;

            for (; i < recipe.length; i++) {
                const c = recipe[i];

                if (inString) {
                    if (escaped) {
                        escaped = false;
                    } else if (c === "\\") {
                        escaped = true;
                    } else if (c === "'") {
                        inString = false;
                    }

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Ensure every operation in the pretty recipe is written as Op_name(args), even if args are empty: 'From Base64()'.
  2. Remove trailing free text after the last operation, or wrap it as an operation.
  3. If you have JSON, pass it through as JSON (it starts with '[' and skips this validator).

Example fix

// before
Utils.parseRecipeConfig('From Base64'); // no parens

// after
Utils.parseRecipeConfig('From Base64()');
// or pass JSON
Utils.parseRecipeConfig('[{"op":"From Base64","args":[]}]');
Defensive patterns

Strategy: validation

Validate before calling

function looksLikePrettyRecipe(s) {
  const trimmed = s.trim();
  if (trimmed.startsWith('[')) return false; // JSON
  return /\(/.test(trimmed) && /^\S/.test(trimmed); // has a paren and a name before it
}

Type guard

null

Try / catch

try { Utils.parseRecipeConfig(recipeStr); } catch (e) {
  if (/Invalid recipe/.test(e.message) && !recipeStr.includes('(')) { /* missing parens */ }
}

Prevention

When it happens

Trigger: A pretty recipe string with no parentheses at all (e.g. 'Some Operation' with no args/parens); trailing text after a valid op that contains no '(' (the while loop's next iteration finds none); a recipe beginning with '(' so the op name before it is empty.

Common situations: Pasting free text or an operation name without its argument list; a multiline pretty recipe where a line was stripped of its parentheses; concatenating recipe fragments incorrectly so a trailing fragment lacks parens.

Related errors


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