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

  1. Check the method spelling against the expression-extensions reference.
  2. Confirm the method is actually an n8n extension (not a plain JS method) — native JS methods are not exposed here.
  3. 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

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


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/3b5c7dbbc05605f7. Report an issue: GitHub.