n8n-io/n8n · error · ExpressionExtensionError

${functionName}() is only callable on type "${haveFunction[0

Error message

${functionName}() is only callable on type "${haveFunction[0].typeName}"

What it means

Same dispatch logic as 325, but the method exists on EXACTLY ONE extension type. The error names that single type so the caller knows what to coerce to.

Source

Thrown at packages/@n8n/expression-runtime/src/extensions/extend.ts:159

	// 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);
	}

	// eslint-disable-next-line @typescript-eslint/no-unsafe-return
	return foundFunction.function(input, args);
}

export function extendOptional(
	input: unknown,
	functionName: string,
	// eslint-disable-next-line @typescript-eslint/no-restricted-types

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Coerce the value to the named type before calling (e.g. `.toNumber().isEven()`, `.toString().toDate()`).
  2. Verify upstream node output types with a quick test or Set node.
  3. Switch to a method defined for the actual runtime type.

Example fix

// before (value arrives as string)
{{ $json.amount.isEven() }}
// after
{{ $json.amount.toNumber().isEven() }}
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof $json.amount !== 'number') {
  throw new Error('Expected number for isEven(); got ' + typeof $json.amount);
}
return $json;

Type guard

const isNumber = (v: unknown): v is number => typeof v === 'number';

Prevention

When it happens

Trigger: Calling a type-specific method on the wrong type — e.g. `.isEven()` on a string, or `.toDate()` on a number that lacks the extension.

Common situations: Upstream delivered a different type than expected (string where a number was assumed, or vice-versa); JSON values whose types changed after a node upgrade.

Related errors


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