n8n-io/n8n · error · ExpressionExtensionError
${functionName}() is only callable on types ${typeNames}
Error message
${functionName}() is only callable on types ${typeNames} What it means
When the requested method name exists on MORE THAN ONE extension type but the input's own type does not provide it, n8n enumerates the types it IS available on, formatted as `"A", "B", and "C"`. This is the multi-type variant of the dispatch-failure branch.
Source
Thrown at packages/@n8n/expression-runtime/src/extensions/extend.ts:155
*/
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);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return foundFunction.function(input, args);
}
View on GitHub (pinned to 5ac6606e81)
Solutions
- Convert the value to one of the listed types first (`.toString()`, `.toNumber()`, `.toDateTime()`).
- Use a method that is actually defined for the current value's type.
- Inspect the upstream node output to confirm the runtime type.
Example fix
// before (count is a number, but the method needs a string)
{{ $json.count.someSharedMethod() }}
// after
{{ $json.count.toString().someSharedMethod() }} Defensive patterns
Strategy: type-guard
Validate before calling
// Confirm the value's runtime type matches one of the types listed in the error before calling the method:
const t = Array.isArray($json.x) ? 'array' : $json.x instanceof Date ? 'date' : typeof $json.x;
if (!['string','number'].includes(t)) {
throw new Error(`Method not available on type: ${t}`);
}
return $json; Type guard
const isStringOrNumber = (v: unknown): v is string | number => typeof v === 'string' || typeof v === 'number';
Prevention
- Coerce values to a listed type before calling shared methods (`.toString()`, `.toNumber()`).
- Inspect upstream node output types before writing the expression.
- Prefer type-specific methods over shared ones when the type is known.
When it happens
Trigger: Calling a method that exists for several types but not for the current value's type — e.g. calling a string/number-shared method on a plain object.
Common situations: Type mismatch in the expression; assuming a method works on any value; upstream node returned an unexpected type (object vs primitive).
Related errors
- ${functionName}() is only callable on type "${haveFunction[0
- 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/e9e6281e915b2cce.
Report an issue: GitHub.