{"record":{"id":"45a713571cb47032","repo":"n8n-io/n8n","slug":"unknown-identifier-identifier-is-not-defined","errorCode":null,"errorMessage":"Unknown identifier: '${identifier}' is not defined","messagePattern":"Unknown identifier: '(.+?)' is not defined","errorType":"exception","errorClass":"UnknownIdentifierError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts","lineNumber":218,"sourceCode":"\t\tvalidateCallExpression(node, this.sourceCode);\n\n\t\t// Get the function to call\n\t\tlet func: unknown;\n\t\tlet thisArg: unknown;\n\n\t\tif (node.callee.type === 'Identifier') {\n\t\t\t// Direct function call: workflow(...), node(...), etc.\n\t\t\tconst name = node.callee.name;\n\n\t\t\tif (this.sdkFunctions.has(name)) {\n\t\t\t\tfunc = this.sdkFunctions.get(name);\n\t\t\t} else {\n\t\t\t\t// Check variables, including auto-renamed ones\n\t\t\t\tconst resolvedName = this.renamedVariables.get(name) ?? name;\n\t\t\t\tif (this.variables.has(resolvedName)) {\n\t\t\t\t\tfunc = this.variables.get(resolvedName);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new UnknownIdentifierError(name, node.callee.loc ?? undefined, this.sourceCode);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (node.callee.type === 'MemberExpression') {\n\t\t\t// Method call: wf.add(...), node.to(...), etc.\n\t\t\tconst memberExpr = node.callee;\n\t\t\tvalidateMemberExpression(memberExpr, this.sourceCode);\n\n\t\t\t// Handle Super type (super keyword) - not supported in SDK code\n\t\t\tif (memberExpr.object.type === 'Super') {\n\t\t\t\tthrow new UnsupportedNodeError(\n\t\t\t\t\t'super keyword is not supported in SDK code',\n\t\t\t\t\tmemberExpr.object.loc ?? undefined,\n\t\t\t\t\tthis.sourceCode,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get method name\n\t\t\tlet methodName: string;","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts#L200-L236","documentation":"When you call a function by bare identifier (`foo()`), the interpreter resolves the name from `sdkFunctions` (injected SDK builders) first, then from `variables` (declared `const`s, including auto-renamed ones). If the name is in neither map, it throws `UnknownIdentifierError`. This prevents calling arbitrary globals or functions that were never declared in SDK scope.","triggerScenarios":"Writing `myHelper()` where `myHelper` is not declared and not an SDK function; or calling a blocked global by name. At interpreter.ts:210-219, the name is checked against `sdkFunctions`, then `renamedVariables`/`variables`; if both miss, the throw fires. Note: blocked globals like `fetch`, `console`, `require` are caught separately by `validateCallExpression` or `validateIdentifier`.","commonSituations":"Typo in a builder function name (`worflow` instead of `workflow`); referencing a helper function that doesn't exist in SDK scope; expecting a standard global like `parseInt` or `console.log` to be callable.","solutions":["Check spelling against the SDK function list: `workflow`, `node`, `trigger`, `sticky`, `placeholder`, `newCredential`, `ifElse`, `switchCase`, `merge`, `splitInBatches`, `nextBatch`, `languageModel`, `memory`, `tool`, `outputParser`, `embedding`, `embeddings`, `vectorStore`, `retriever`, `documentLoader`, `textSplitter`, `reranker`, `fromAi`, `nodeJson`","If calling your own function, note that arrow/function declarations are also blocked — move the logic to a Code node","Verify the identifier wasn't auto-renamed (subnode builders like `tool` get renamed, not the call)"],"exampleFix":"// before\nconst result = worflow({ name: 'My WF' }); // typo\n\n// after\nconst result = workflow({ name: 'My WF' });","handlingStrategy":"validation","validationCode":"import { ALLOWED_SDK_FUNCTIONS } from '@n8n/workflow-sdk/ast-interpreter/validators';\n\nfunction findUndefinedCalls(code: string, declaredVars: Set<string>): string[] {\n  const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });\n  const undefined: string[] = [];\n  walk(ast, (node) => {\n    if (\n      node.type === 'CallExpression' &&\n      node.callee.type === 'Identifier' &&\n      !ALLOWED_SDK_FUNCTIONS.has(node.callee.name) &&\n      !declaredVars.has(node.callee.name)\n    ) {\n      undefined.push(node.callee.name);\n    }\n  });\n  return undefined;\n}","typeGuard":null,"tryCatchPattern":"import { UnknownIdentifierError } from '@n8n/workflow-sdk/ast-interpreter/errors';\n\ntry {\n  interpretSDKCode(sdkCode, sdkFunctions);\n} catch (e) {\n  if (e instanceof UnknownIdentifierError) {\n    // show the identifier name and suggest checking spelling or declaring it\n  }\n  throw e;\n}","preventionTips":["Keep a list of valid SDK function names visible when authoring","Spell-check builder names against `ALLOWED_SDK_FUNCTIONS`","Remember that standard globals (`parseInt`, `console`, etc.) are not available"],"tags":["sdk-interpreter","identifier","undefined-function","typo"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}