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

  1. 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`
  2. If calling your own function, note that arrow/function declarations are also blocked — move the logic to a Code node
  3. 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

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


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