gchq/CyberChef · error · TypeError

Recipe can only contain function names or functions

Error message

Recipe can only contain function names or functions

What it means

Thrown by NodeRecipe._validateIngredient as the final fallback when the ingredient is neither a string (op name), nor a function (operation class), nor an object with an 'op' property. It is the catch-all for structurally invalid recipe entries.

Source

Thrown at src/node/NodeRecipe.mjs:64

        } 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
     */
    _parseConfig(recipeConfig) {
        if (!recipeConfig) {
            this.opList = [];
            return;
        }

        if (!Array.isArray(recipeConfig)) {
            recipeConfig = [recipeConfig];
        }

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Use one of the supported shapes: an operation name string, an operation function, or {op: "<name>", args: [...]} with the 'op' key (not 'operation'/'name').
  2. Remove null/undefined/empty entries before building the recipe.
  3. Validate each entry's shape before passing the array to chef.bake.

Example fix

// before: wrong key
chef.bake(input, [{operation:"From Hex", args:["None"]}]);
// after
chef.bake(input, [{op:"From Hex", args:["None"]}]);
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidIngredient(ing) {
  return typeof ing === "string" || typeof ing === "function" || (ing && typeof ing === "object" && "op" in ing);
}
function assertRecipeShape(recipe) {
  for (const ing of recipe) if (!isValidIngredient(ing)) throw new Error("Recipe entry must be a name, function, or {op, args?}");
}

Type guard

const isRecipeEntry = (ing) => typeof ing === "string" || typeof ing === "function" || (ing != null && typeof ing === "object" && Object.prototype.hasOwnProperty.call(ing, "op"));

Try / catch

try { chef.bake(input, recipe); } catch (e) { if (e instanceof TypeError && /only contain function names or functions/.test(e.message)) { /* fix entry shape to {op, args?} */ } else throw e; }

Prevention

When it happens

Trigger: A recipe array contains a number, boolean, null, array, or an object without an 'op' key. Example: [{operation: "From Hex"}] (wrong key — must be 'op') or [42].

Common situations: Wrong recipe schema (using 'operation'/'name' instead of 'op'); passing a nested array; nulls from optional-chaining bugs when building the recipe dynamically.

Related errors


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