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-typesView on GitHub (pinned to 5ac6606e81)
Solutions
- Coerce the value to the named type before calling (e.g. `.toNumber().isEven()`, `.toString().toDate()`).
- Verify upstream node output types with a quick test or Set node.
- 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
- Coerce with `.toNumber()` / `.toString()` to land on the single supported type.
- Verify the upstream node's output schema.
- Switch to a method defined for the actual runtime type.
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
- ${functionName}() is only callable on types ${typeNames}
- isEven() is only callable on integers
- isOdd() is only callable on integers
- Reflector field "${fieldName}" must contain only strings
- Reflector merge[${index}] must be an object
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/c7e36d82ee8e905f.
Report an issue: GitHub.