gchq/CyberChef · error · OperationError

${this.name} must be one of the following: ${permittedOption

Error message

${this.name} must be one of the following: ${permittedOptions.join(", ")}.

What it means

Thrown by Ingredient.validate() option checks (line 153) when type is 'option', defaultValue is an Array, and after lowercasing, checkVal matches none of the permitted options. Permitted options are defaultValue entries that are strings AND do not match the placeholder regex /^[/?[a-z0-9 -()^]+]$/i (bracketed placeholders like [Alpha] are excluded). Matching is case-insensitive.

Source

Thrown at src/core/Ingredient.mjs:153

            if (typeof this.min === "number" && checkVal < this.min) {
                throw new OperationError(`${this.name} must be greater than or equal to ${this.min}.`);
            }
            if (typeof this.max === "number" && checkVal > this.max) {
                throw new OperationError(`${this.name} must be less than or equal to ${this.max}.`);
            }
        }

        // 4. option checks
        if (this.type === "option") {
            if (Array.isArray(this.defaultValue)) {
                const permittedOptions = this.defaultValue.filter(opt => {
                    if (typeof opt !== "string") return false;
                    return !opt.match(/^\[\/?[a-z0-9 -()^]+\]$/i);
                });
                const valStr = (checkVal !== null && checkVal !== undefined) ? String(checkVal).toLowerCase() : "";
                const matchedOption = permittedOptions.find(opt => opt.toLowerCase() === valStr);
                if (!matchedOption) {
                    throw new OperationError(`${this.name} must be one of the following: ${permittedOptions.join(", ")}.`);
                }
            }
        }

        // 5. argSelector checks
        if (this.type === "argSelector") {
            if (Array.isArray(this.defaultValue)) {
                const permittedOptions = this.defaultValue
                    .map(opt => opt.name)
                    .filter(optName => {
                        if (typeof optName !== "string") return false;
                        return !optName.match(/^\[\/?[a-z0-9 -()^]+\]$/i);
                    });
                const valStr = (checkVal !== null && checkVal !== undefined) ? String(checkVal).toLowerCase() : "";
                const matchedOption = permittedOptions.find(opt => opt.toLowerCase() === valStr);
                if (!matchedOption) {
                    throw new OperationError(`${this.name} must be one of the following: ${permittedOptions.join(", ")}.`);
                }

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Set the ingredient to one of the values listed in the error message (case-insensitive).
  2. If the operation's options changed, update the recipe to a currently-valid option.
  3. Confirm defaultValue in the operation config actually lists real options, not only bracketed placeholders.

Example fix

// before - permitted: CBC, ECB
op.ingValues = ['CFB'];

// after
op.ingValues = ['CBC'];
Defensive patterns

Strategy: validation

Validate before calling

const permitted = defaultValue.filter(o => typeof o === 'string' && !/^[/?[a-z0-9 -()^]+]$/i.test(o));
if (!permitted.some(o => o.toLowerCase() === String(val).toLowerCase())) {
  throw new Error(`${name} not in ${permitted.join(', ')}`);
}

Type guard

function isValidOption(v, permitted): v is string { return typeof v === 'string' && permitted.some(o => o.toLowerCase() === v.toLowerCase()); }

Try / catch

try { op.ingValues = [val]; } catch (e) { if (/must be one of the following/.test(e.message)) { val = permitted[0]; } }

Prevention

When it happens

Trigger: An option ingredient (dropdown) receives a value that is not one of its declared options; e.g. a 'Mode' option with permitted ['CBC','ECB'] gets 'CFB'; or the only entries are bracketed placeholders so permittedOptions is empty and nothing matches.

Common situations: Recipe references an option value renamed or removed in a newer operation version; typo in the option value; locale/case mismatch; copying an option arg from a different operation.

Related errors


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