n8n-io/n8n · error · ExpressionExtensionError
Unknown expression function: ${functionName}
Error message
Unknown expression function: ${functionName} What it means
When `extend()` is asked to run a function name that exists on NO extension type at all (and the input is defined — `checkIfValueDefinedOrThrow` passed), it throws `Unknown expression function`. This is the runtime equivalent of 'method does not exist on this value'.
Source
Thrown at packages/@n8n/expression-runtime/src/extensions/extend.ts:149
/**
* Extender function injected by expression extension plugin to allow calls to extensions.
*
* ```ts
* extend(input, "functionName", [...args]);
* ```
*/
export function extend(input: unknown, functionName: string, args: unknown[]) {
const foundFunction = findExtendedFunction(input, functionName);
// No type specific or generic function found. Check to see if
// any types have a function with that name. Then throw an error
// letting the user know the available types.
if (!foundFunction) {
checkIfValueDefinedOrThrow(input, functionName);
const haveFunction = EXTENSION_OBJECTS.filter((v) => functionName in v.functions);
if (!haveFunction.length) {
// This shouldn't really be possible but we should cover it anyway
throw new ExpressionExtensionError(`Unknown expression function: ${functionName}`);
}
if (haveFunction.length > 1) {
const lastType = `"${haveFunction.pop()!.typeName}"`;
const typeNames = `${haveFunction.map((v) => `"${v.typeName}"`).join(', ')}, and ${lastType}`;
throw new ExpressionExtensionError(
`${functionName}() is only callable on types ${typeNames}`,
);
} else {
throw new ExpressionExtensionError(
`${functionName}() is only callable on type "${haveFunction[0].typeName}"`,
);
}
}
if (foundFunction.type === 'native') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return foundFunction.function.apply(input, args);View on GitHub (pinned to 5ac6606e81)
Solutions
- Check the method spelling against the expression-extensions reference.
- Confirm the method is actually an n8n extension (not a plain JS method) — native JS methods are not exposed here.
- If the method exists but on the wrong type, see errors 325/326 for the type-mismatch variants.
Example fix
// before
{{ $json.price.toIntiger() }}
// after
{{ $json.price.toInt() }} Defensive patterns
Strategy: validation
Validate before calling
const KNOWN = new Set(['toInt','toFloat','toDateTime','toDate','toDate','isEmpty','isNotEmpty','hash','intersection','unique','isEven','isOdd','floor','ceil','round','ifEmpty','removeFieldsContaining','keepFieldsContaining','urlEncode','urlDecode']);
const name = $json.methodName;
if (typeof name === 'string' && !KNOWN.has(name)) {
throw new Error(`Unknown expression function: ${name}`);
}
return $json; Type guard
const isKnownExtension = (name: string, registry: Set<string>): name is string => registry.has(name);
Prevention
- Cross-check method names against the expression-extensions reference.
- Remember native JS methods are NOT exposed as extensions.
- After a version upgrade, re-verify any custom extension names you depend on.
When it happens
Trigger: Calling a misspelled or nonexistent extension method: `{{ $json.x.frobnicate() }}`, `{{ $json.y.toIntiger() }}`, `{{ $json.z.toFixed(2) }}` (regular JS method, not an extension).
Common situations: Method-name typo; using a method that was renamed/removed in a version upgrade; confusing built-in JS methods with n8n expression extensions.
Related errors
- intersection(): expected array arg, e.g. .intersection([1, 2
- isBetween(): expected exactly two args
- Unsupported unit '${String(errorUnit)}'. Supported: ${durati
- Cannot access "${name}" via expression extension due to secu
- ${functionName}() is only callable on types ${typeNames}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/3b5c7dbbc05605f7.
Report an issue: GitHub.