n8n-io/n8n · error · UnknownIdentifierError
Unknown identifier: '${identifier}' is not defined
Error message
Unknown identifier: '${identifier}' is not defined What it means
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.
Source
Thrown at packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts:218
validateCallExpression(node, this.sourceCode);
// Get the function to call
let func: unknown;
let thisArg: unknown;
if (node.callee.type === 'Identifier') {
// Direct function call: workflow(...), node(...), etc.
const name = node.callee.name;
if (this.sdkFunctions.has(name)) {
func = this.sdkFunctions.get(name);
} else {
// Check variables, including auto-renamed ones
const resolvedName = this.renamedVariables.get(name) ?? name;
if (this.variables.has(resolvedName)) {
func = this.variables.get(resolvedName);
} else {
throw new UnknownIdentifierError(name, node.callee.loc ?? undefined, this.sourceCode);
}
}
} else if (node.callee.type === 'MemberExpression') {
// Method call: wf.add(...), node.to(...), etc.
const memberExpr = node.callee;
validateMemberExpression(memberExpr, this.sourceCode);
// Handle Super type (super keyword) - not supported in SDK code
if (memberExpr.object.type === 'Super') {
throw new UnsupportedNodeError(
'super keyword is not supported in SDK code',
memberExpr.object.loc ?? undefined,
this.sourceCode,
);
}
// Get method name
let methodName: string;View on GitHub (pinned to 5ac6606e81)
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)
Example fix
// before
const result = worflow({ name: 'My WF' }); // typo
// after
const result = workflow({ name: 'My WF' }); Defensive patterns
Strategy: validation
Validate before calling
import { ALLOWED_SDK_FUNCTIONS } from '@n8n/workflow-sdk/ast-interpreter/validators';
function findUndefinedCalls(code: string, declaredVars: Set<string>): string[] {
const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });
const undefined: string[] = [];
walk(ast, (node) => {
if (
node.type === 'CallExpression' &&
node.callee.type === 'Identifier' &&
!ALLOWED_SDK_FUNCTIONS.has(node.callee.name) &&
!declaredVars.has(node.callee.name)
) {
undefined.push(node.callee.name);
}
});
return undefined;
} Try / catch
import { UnknownIdentifierError } from '@n8n/workflow-sdk/ast-interpreter/errors';
try {
interpretSDKCode(sdkCode, sdkFunctions);
} catch (e) {
if (e instanceof UnknownIdentifierError) {
// show the identifier name and suggest checking spelling or declaring it
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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`.
Common situations: 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.
Related errors
- Unknown identifier: '${name}' is not defined
- Unknown expression function: ${functionName}
- Unsupported syntax: 'Destructuring in variable declaration'
- '${name}' is a reserved SDK function name and cannot be used
- Expression nesting too deep (possible cycle in method chain)
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/45a713571cb47032.
Report an issue: GitHub.