n8n-io/n8n · error · UnsupportedNodeError
Unsupported syntax: '${nodeType}' is not allowed in SDK code
Error message
Unsupported syntax: '${nodeType}' is not allowed in SDK code What it means
Thrown as UnsupportedNodeError (extends InterpreterError) by the SDK AST interpreter when a top-level statement is not VariableDeclaration, ExpressionStatement, or ExportDefaultDeclaration. The message lists the offending node type and, when source location is present, appends a code frame. This is a sandbox guard: only a restricted subset of JS is evaluable as SDK code.
Source
Thrown at packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts:83
* Interpret the AST program and return the result.
*/
interpret(ast: ESTree.Program): unknown {
let result: unknown;
for (const stmt of ast.body) {
validateNodeType(stmt, this.sourceCode);
switch (stmt.type) {
case 'VariableDeclaration':
this.visitVariableDeclaration(stmt);
break;
case 'ExpressionStatement':
result = this.evaluate(stmt.expression);
break;
case 'ExportDefaultDeclaration':
return this.evaluate(stmt.declaration as ESTree.Expression);
default:
throw new UnsupportedNodeError(stmt.type, stmt.loc ?? undefined, this.sourceCode);
}
}
return result;
}
/**
* Process a variable declaration.
*/
private visitVariableDeclaration(node: ESTree.VariableDeclaration): void {
// Only allow const declarations
if (node.kind !== 'const') {
throw new SecurityError(
node.kind,
node.loc ?? undefined,
this.sourceCode,
`'${node.kind}' declarations are not allowed. Use 'const' only.`,
);View on GitHub (pinned to 5ac6606e81)
Solutions
- Restructure SDK code to use only const declarations, expression statements, and an optional export default.
- Move logic into allowed SDK function calls instead of defining helper functions at top level.
- Replace control-flow statements with expressions (e.g. ternaries, allowed SDK helpers).
Example fix
// before
function transform(x) { return x.toUpperCase(); }
export default transform(input);
// after
const transform = (x) => x.toUpperCase();
export default transform(input); Defensive patterns
Strategy: validation
Validate before calling
import { parseSDKCode } from '@n8n/workflow-sdk';
import { UnsupportedNodeError } from '@n8n/workflow-sdk';
function preflightSDKCode(code: string): void {
const ast = parseSDKCode(code); // throws on parse errors
const allowed = new Set(['VariableDeclaration', 'ExpressionStatement', 'ExportDefaultDeclaration']);
for (const stmt of ast.body) {
if (!allowed.has(stmt.type)) {
throw new Error(`SDK code may not contain '${stmt.type}'. Use only const declarations, expression statements, and an optional export default.`);
}
}
} Type guard
import type { Program, Statement } from 'estree';
const ALLOWED_SDK_STATEMENTS = new Set<Statement['type']>([
'VariableDeclaration',
'ExpressionStatement',
'ExportDefaultDeclaration',
]);
function isAllowedSdkStatement(stmt: Statement): boolean {
return ALLOWED_SDK_STATEMENTS.has(stmt.type);
} Try / catch
try {
return interpret(code, sdkFunctions);
} catch (e) {
if (e?.name === 'UnsupportedNodeError') {
return { error: 'This SDK code uses unsupported syntax.', detail: e.message };
}
throw e;
} Prevention
- Restrict SDK code to const declarations, expression statements, and one export default.
- Validate the AST before evaluation when accepting user-authored SDK code.
- Surface UnsupportedNodeError messages with their code frame to help authors fix the syntax.
When it happens
Trigger: Authoring SDK code with a FunctionDeclaration, IfStatement, ForStatement, ReturnStatement at top level, a class declaration, or any other statement kind outside the allowed three. Also triggered by code that the parser accepts but the interpreter refuses (e.g. a try/catch block, a switch).
Common situations: Users pasting ordinary JS into an SDK code box expecting general execution; tooling that emits scaffolding (imports, functions) around the SDK snippet; attempting control flow or function definitions that the SDK vocabulary disallows.
Related errors
- '${node.kind}' declarations are not allowed. Use 'const' onl
- ${label} "${candidate}" escapes ${root}
- Invalid skill at ${sourceDirectory}: ${errors.join('; ')}
- Webhook URL must use HTTPS. Got: ${url.protocol}
- Webhook URL cannot target localhost
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/90649245153b5b31.
Report an issue: GitHub.