{"record":{"id":"55c829292498883d","repo":"n8n-io/n8n","slug":"unsupported-syntax-callee-type-node-callee-typ","errorCode":null,"errorMessage":"Unsupported syntax: 'Callee type ${node.callee.type}' is not allowed in SDK code","messagePattern":"Unsupported syntax: 'Callee type (.+?)' is not allowed in SDK code","errorType":"exception","errorClass":"UnsupportedNodeError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts","lineNumber":288,"sourceCode":"\n\t\t\t// Validate method name against allowlist\n\t\t\tif (!isAllowedMethod(methodName)) {\n\t\t\t\tthrow new SecurityError(\n\t\t\t\t\tmethodName,\n\t\t\t\t\tmemberExpr.property.loc ?? undefined,\n\t\t\t\t\tthis.sourceCode,\n\t\t\t\t\t`Method '${methodName}' is not an allowed SDK method. ` +\n\t\t\t\t\t\t`Allowed methods: ${allowedMethodNames().join(', ')}. ` +\n\t\t\t\t\t\t'Native array/string methods are not available in SDK code; ' +\n\t\t\t\t\t\t'use a Code node or an n8n expression for runtime logic.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (thisArg && typeof thisArg === 'object') {\n\t\t\t\tfunc = (thisArg as Record<string, unknown>)[methodName];\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new UnsupportedNodeError(\n\t\t\t\t`Callee type ${node.callee.type}`,\n\t\t\t\tnode.callee.loc ?? undefined,\n\t\t\t\tthis.sourceCode,\n\t\t\t);\n\t\t}\n\n\t\tif (typeof func !== 'function') {\n\t\t\tthrow new InterpreterError(\n\t\t\t\t'Cannot call non-function',\n\t\t\t\tnode.loc ?? undefined,\n\t\t\t\tthis.sourceCode,\n\t\t\t);\n\t\t}\n\n\t\t// Evaluate arguments\n\t\tconst args = node.arguments.map((arg) => this.evaluate(arg));\n\n\t\t// Call the function","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts#L270-L306","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Assign the intermediate result to a `const`, then call a method on it: `const factory = getBuilder(); factory.add(...)`","Restructure to use SDK builder method chaining instead of nested calls","Note: even after assigning, you can only call SDK-allowed methods on the result"],"exampleFix":"// before\nconst result = getFactory()({ name: 'X' });\n\n// after\nconst factory = getFactory();\nconst result = factory({ name: 'X' });\n// (but note: arrow/function expressions are also blocked in SDK code)","handlingStrategy":"validation","validationCode":"// Detect non-Identifier/non-MemberExpression callees\nfunction hasComplexCallee(code: string): boolean {\n  const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });\n  let found = false;\n  walk(ast, (node) => {\n    if (\n      node.type === 'CallExpression' &&\n      node.callee.type !== 'Identifier' &&\n      node.callee.type !== 'MemberExpression'\n    ) {\n      found = true;\n    }\n  });\n  return found;\n}","typeGuard":null,"tryCatchPattern":"import { UnsupportedNodeError } from '@n8n/workflow-sdk/ast-interpreter/errors';\n\ntry {\n  interpretSDKCode(sdkCode, sdkFunctions);\n} catch (e) {\n  if (e instanceof UnsupportedNodeError && e.message.includes('Callee type')) {\n    // instruct user to assign intermediate result to a const first\n  }\n  throw e;\n}","preventionTips":["Never call the result of a call directly: `getFn()()` is invalid","Assign intermediate results to `const` variables, then call methods on them","SDK code does not support higher-order function patterns"],"tags":["sdk-interpreter","callee","call-expression","higher-order"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}