n8n-io/n8n · error · UnsupportedNodeError

Unsupported syntax: 'Callee type ${node.callee.type}' is not

Error message

Unsupported syntax: 'Callee type ${node.callee.type}' is not allowed in SDK code

What it means

A call expression's callee (the function being invoked) must be either an `Identifier` (`foo()`) or a `MemberExpression` (`obj.method()`). Any other callee type — such as a `CallExpression` (`getFn()()`) — is rejected at interpreter.ts:288 because the interpreter does not support calling the return value of another call, which would require first-class function evaluation the sandbox doesn't provide.

Source

Thrown at packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts:288

			// Validate method name against allowlist
			if (!isAllowedMethod(methodName)) {
				throw new SecurityError(
					methodName,
					memberExpr.property.loc ?? undefined,
					this.sourceCode,
					`Method '${methodName}' is not an allowed SDK method. ` +
						`Allowed methods: ${allowedMethodNames().join(', ')}. ` +
						'Native array/string methods are not available in SDK code; ' +
						'use a Code node or an n8n expression for runtime logic.',
				);
			}

			if (thisArg && typeof thisArg === 'object') {
				func = (thisArg as Record<string, unknown>)[methodName];
			}
		} else {
			throw new UnsupportedNodeError(
				`Callee type ${node.callee.type}`,
				node.callee.loc ?? undefined,
				this.sourceCode,
			);
		}

		if (typeof func !== 'function') {
			throw new InterpreterError(
				'Cannot call non-function',
				node.loc ?? undefined,
				this.sourceCode,
			);
		}

		// Evaluate arguments
		const args = node.arguments.map((arg) => this.evaluate(arg));

		// Call the function

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Assign the intermediate result to a `const`, then call a method on it: `const factory = getBuilder(); factory.add(...)`
  2. Restructure to use SDK builder method chaining instead of nested calls
  3. Note: even after assigning, you can only call SDK-allowed methods on the result

Example fix

// before
const result = getFactory()({ name: 'X' });

// after
const factory = getFactory();
const result = factory({ name: 'X' });
// (but note: arrow/function expressions are also blocked in SDK code)
Defensive patterns

Strategy: validation

Validate before calling

// Detect non-Identifier/non-MemberExpression callees
function hasComplexCallee(code: string): boolean {
  const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });
  let found = false;
  walk(ast, (node) => {
    if (
      node.type === 'CallExpression' &&
      node.callee.type !== 'Identifier' &&
      node.callee.type !== 'MemberExpression'
    ) {
      found = true;
    }
  });
  return found;
}

Try / catch

import { UnsupportedNodeError } from '@n8n/workflow-sdk/ast-interpreter/errors';

try {
  interpretSDKCode(sdkCode, sdkFunctions);
} catch (e) {
  if (e instanceof UnsupportedNodeError && e.message.includes('Callee type')) {
    // instruct user to assign intermediate result to a const first
  }
  throw e;
}

Prevention

When it happens

Trigger: Writing `getBuilder()()` (calling the result of a call), or `(expr)()` patterns. The `visitCallExpression` method only branches on `node.callee.type === 'Identifier'` and `=== 'MemberExpression'`; the `else` at line 287 catches everything else.

Common situations: Higher-order function patterns; IIFE-style calls; chaining a call on the result of a factory function; code that treats builders as first-class values.

Related errors


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