gchq/CyberChef · error · Error

Failed to hydrate operation '${o.name}': ${err}

Error message

Failed to hydrate operation '${o.name}': ${err}

What it means

Thrown by Recipe._hydrateOpList() (line 80) wrapping any exception from constructing an operation instance (new modules[o.module][o.name]()) or from assigning op.ingValues. Notably this throws a plain Error, NOT OperationError. The most common inner cause is operation-not-found: modules[o.module][o.name] is undefined when the recipe references an op name/module that does not exist, so calling it as a constructor throws TypeError. The second cause is an ingValues failure (error 14) wrapped again here.

Source

Thrown at src/core/Recipe.mjs:80

        if (!modules) {
            // Using Webpack Magic Comments to force the dynamic import to be included in the main chunk
            // https://webpack.js.org/api/module-methods/
            modules = await import(/* webpackMode: "eager" */ "./config/modules/OpModules.mjs");
            modules = modules.default;
        }

        this.opList = this.opList.map(o => {
            if (o instanceof Operation) {
                return o;
            } else {
                try {
                    const op = new modules[o.module][o.name]();
                    op.ingValues = o.ingValues;
                    op.breakpoint = o.breakpoint;
                    op.disabled = o.disabled;
                    return op;
                } catch (err) {
                    throw new Error(`Failed to hydrate operation '${o.name}': ${err}`);
                }
            }
        });
    }


    /**
     * Returns the value of the Recipe as it should be displayed in a recipe config.
     *
     * @returns {Object[]}
     */
    get config() {
        return this.opList.map(op => ({
            op: op.name,
            args: op.ingValues,
        }));
    }

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Read the inner ${err}: 'modules[...][...] is not a constructor' / 'undefined is not a constructor' means the op name or module is wrong - verify against the current operation catalogue.
  2. Operation names in recipes use spaces, not underscores; confirm spelling and capitalisation.
  3. If the inner error is an OperationError about an ingredient, fix that arg (see error 14).
  4. Ensure any custom operation is registered in the module tree before hydrating the recipe.

Example fix

// before - wrong op name
recipe = [{ op: 'From_Base64', args: [], module: 'Default' }];

// after
recipe = [{ op: 'From Base64', args: [], module: 'Default' }];
Defensive patterns

Strategy: validation

Validate before calling

import OperationList from './core/config/OperationList.mjs';
const known = new Set(OperationList.map(o => o.op));
function validateRecipeOps(recipe) {
  for (const r of recipe) if (!known.has(r.op)) throw new Error(`Unknown op: ${r.op}`);
}

Type guard

function opExists(name, modules): boolean { return !!(modules && modules.Default && typeof modules.Default[name] === 'function'); }

Try / catch

try { await recipe._hydrateOpList(); } catch (e) {
  if (/Failed to hydrate operation/.test(e.message)) { /* name/module wrong or arg invalid */ }
}

Prevention

When it happens

Trigger: A recipe entry references an operation name that was renamed/removed (e.g. 'From_Base64' vs 'From Base64'); the module key is wrong or missing; the operation exists but one of its args is invalid, so op.ingValues = o.ingValues throws error 14 which gets wrapped here.

Common situations: Loading a recipe saved against an older or newer CyberChef version where an operation was renamed; hand-written recipe JSON with a typo in the op name or module; recipe references a custom operation whose module was not registered.

Related errors


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