n8n-io/n8n · error · UnknownIdentifierError
Unknown identifier: '${name}' is not defined
Error message
Unknown identifier: '${name}' is not defined What it means
When resolving a bare identifier reference (not in a call), the interpreter at interpreter.ts:418-445 checks in order: locally declared variables (including auto-renamed ones), dangerous globals (rejected by `validateIdentifier`), SDK functions, and safe built-ins (`undefined`, `null`, `true`, `false`, `NaN`, `Infinity`). If the name matches none of these, it throws `UnknownIdentifierError`.
Source
Thrown at packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts:445
}
// Check for dangerous globals (only when not shadowed by a local)
validateIdentifier(name, this.getVariableNames(), node, this.sourceCode);
// Check if it's an SDK function
if (this.sdkFunctions.has(name)) {
return this.sdkFunctions.get(name);
}
// Allow certain safe built-ins
if (name === 'undefined') return undefined;
if (name === 'null') return null;
if (name === 'true') return true;
if (name === 'false') return false;
if (name === 'NaN') return NaN;
if (name === 'Infinity') return Infinity;
throw new UnknownIdentifierError(name, node.loc ?? undefined, this.sourceCode);
}
/**
* Visit a template literal.
* Handles n8n runtime variables by preserving them as escaped strings.
*/
private visitTemplateLiteral(node: ESTree.TemplateLiteral): string {
let result = '';
for (let i = 0; i < node.quasis.length; i++) {
const quasi = node.quasis[i];
// Use cooked value (with escape sequences processed), or raw if cooked is null
result += quasi.value.cooked ?? quasi.value.raw;
// If there's an expression after this quasi
if (i < node.expressions.length) {
const expr = node.expressions[i];
const value = this.evaluateTemplateExpression(expr);View on GitHub (pinned to 5ac6606e81)
Solutions
- Declare the variable with `const` before referencing it
- Check spelling against declared variable names
- For globals: use SDK alternatives (e.g., `$now`/`$today` for dates, n8n expressions for Math)
Example fix
// before const result = myVarible; // typo // after const result = myVariable;
Defensive patterns
Strategy: validation
Validate before calling
import { ALLOWED_SDK_FUNCTIONS } from '@n8n/workflow-sdk/ast-interpreter/validators';
const SAFE_BUILTINS = new Set(['undefined', 'null', 'true', 'false', 'NaN', 'Infinity']);
function findUndefinedReferences(code: string, declaredVars: Set<string>): string[] {
const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });
const undefined: string[] = [];
walk(ast, (node) => {
if (
node.type === 'Identifier' &&
!declaredVars.has(node.name) &&
!ALLOWED_SDK_FUNCTIONS.has(node.name) &&
!SAFE_BUILTINS.has(node.name)
) {
// Exclude property names and callee names (they are contextual)
undefined.push(node.name);
}
});
return [...new Set(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 declaring it or checking spelling
}
throw e;
} Prevention
- Declare all variables with `const` before referencing them
- Spell-check variable names consistently
- Remember that globals like `console`, `Math`, `Date` are blocked — use SDK alternatives
When it happens
Trigger: Referencing an undeclared variable: `x` where `x` was never declared with `const`. Note that blocked globals like `console`, `Math`, `Date`, `process`, `fetch` are caught earlier by `validateIdentifier` (throwing `SecurityError`), so this throw is specifically for names that are simply unknown — not dangerous, just undefined.
Common situations: Typo in a variable name; referencing a variable from an outer scope that isn't in SDK scope; using an identifier that was declared in a different code path.
Related errors
- Unknown identifier: '${identifier}' 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/ba87f11a959c0fcb.
Report an issue: GitHub.