gchq/CyberChef · error · TypeError

Inputted function not a Chef operation.

Error message

Inputted function not a Chef operation.

What it means

Thrown by NodeRecipe._validateIngredient when the ingredient is a function that is not flowControl but is not present in the registered operations list. It distinguishes 'wrong kind of function' from 'unknown name' (714) and 'flowControl' (715).

Source

Thrown at src/node/NodeRecipe.mjs:54

            const op = operations.find((op) => {
                return sanitise(op.opName) === sanitise(ing);
            });
            if (op) {
                // Need to validate against case 2
                return this._validateIngredient(op);
            } else {
                throw new TypeError(`Couldn't find an operation with name '${ing}'.`);
            }
        // CASE operation given. Check its a chef operation and check its not flowcontrol
        } else if (typeof ing === "function") {
            if (ing.flowControl) {
                throw new TypeError(`flowControl operations like ${ing.opName} are not currently allowed in recipes for chef.bake in the Node API`);
            }

            if (operations.includes(ing)) {
                return ing;
            } else {
                throw new TypeError("Inputted function not a Chef operation.");
            }
        // CASE: op, maybe with configuration
        } else if (ing.op) {
            const sanitisedOp = this._validateIngredient(ing.op);
            if (ing.args) {
                return {op: sanitisedOp, args: ing.args};
            }
            return sanitisedOp;
        } else {
            throw new TypeError("Recipe can only contain function names or functions");
        }
    }


    /**
     * Parse an opList from a recipeConfig and assign it to the recipe's opList.
     * @param {String | Function | String[] | Function[] | [String | Function]} recipeConfig
     */

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Pass operations by their canonical string name (handled by case 714's lookup) rather than as function references.
  2. Ensure the operation you import is the same module instance the Node API uses (same node_modules/CyberChef).
  3. Don't put arbitrary functions in a Node recipe — the API only accepts Chef operations or their names.

Example fix

// before: imported op is a different instance than the API's
import {FromHex} from "cyberchef/src/...";
chef.bake(input, [FromHex]);
// after: reference by name
chef.bake(input, ["From Hex"]);
Defensive patterns

Strategy: type-guard

Validate before calling

import { operations } from "cyberchef/src/node/index.mjs";
function assertOpsRegistered(recipe) {
  for (const ing of recipe) if (typeof ing === "function" && !ing.flowControl && !operations.includes(ing))
    throw new Error("Function is not a registered Chef operation; pass by name instead.");
}

Type guard

const isChefOperation = (ing) => typeof ing === "function" && operations.includes(ing);

Try / catch

try { chef.bake(input, recipe); } catch (e) { if (e instanceof TypeError && /not a Chef operation/.test(e.message)) { /* pass op by name string */ } else throw e; }

Prevention

When it happens

Trigger: A plain JS function, or an operation class from a different CyberChef build/fork, is passed in the recipe array. operations.includes(ing) is a reference check, so an operation imported from a mismatched version is a different object and fails the includes test.

Common situations: Importing an operation class from source while the Node API bundled its own copy (two module instances); passing a custom function thinking it will be invoked; mixing built recipe JSON with freshly imported classes.

Related errors


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