n8n-io/n8n · error · UnsupportedNodeError

Unsupported syntax: 'Destructuring in variable declaration'

Error message

Unsupported syntax: 'Destructuring in variable declaration' is not allowed in SDK code

What it means

The SDK interpreter only supports simple `const name = value` declarations with a single identifier name. Destructuring patterns (`const { a, b } = obj` or `const [x, y] = arr`) are rejected because the interpreter stores variables in a flat `Map<string, unknown>` keyed by one identifier per declarator. This restriction keeps the sandboxed evaluation model simple and predictable — the interpreter never has to pattern-match or bind multiple names from one initializer.

Source

Thrown at packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts:106

	}

	/**
	 * 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.`,
			);
		}

		for (const declarator of node.declarations) {
			if (declarator.id.type !== 'Identifier') {
				throw new UnsupportedNodeError(
					'Destructuring in variable declaration',
					declarator.loc ?? undefined,
					this.sourceCode,
				);
			}

			const name = declarator.id.name;

			// Check for SDK function name collisions
			if (isAllowedSDKFunction(name)) {
				if (isAutoRenameableSDKFunction(name)) {
					// Auto-rename subnode variables that collide with SDK function names
					const safeName = this.generateSafeName(name);
					const value = declarator.init ? this.evaluate(declarator.init) : undefined;
					this.renamedVariables.set(name, safeName);
					this.variables.set(safeName, value);
					continue;
				}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Replace destructuring with one `const` per field: `const name = obj.name; const type = obj.type;`
  2. Access properties inline where needed instead of binding them first
  3. Move complex unpacking into a Code node and pass the result forward

Example fix

// before
const { name, typeVersion } = node.parameters;

// after
const name = node.parameters.name;
const typeVersion = node.parameters.typeVersion;
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check SDK code for destructuring before interpreting
import { parse } from 'acorn';

function hasDestructuring(code: string): boolean {
  const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });
  let found = false;
  walk(ast, (node) => {
    if (
      node.type === 'VariableDeclarator' &&
      (node.id.type === 'ObjectPattern' || node.id.type === 'ArrayPattern')
    ) {
      found = true;
    }
  });
  return found;
}

if (hasDestructuring(sdkCode)) {
  // reject before calling interpretSDKCode
}

Try / catch

import { UnsupportedNodeError } from '@n8n/workflow-sdk/ast-interpreter/errors';

try {
  interpretSDKCode(sdkCode, sdkFunctions);
} catch (e) {
  if (e instanceof UnsupportedNodeError && e.message.includes('Destructuring')) {
    // prompt user to rewrite as separate const declarations
  }
  throw e;
}

Prevention

When it happens

Trigger: Writing `const { name, type } = node.parameters` or `const [first, second] = items` in SDK code passed to `interpretSDKCode()`. The parser accepts the syntax (valid JS), but `visitVariableDeclaration` at interpreter.ts:105 checks `declarator.id.type !== 'Identifier'` and throws when the id is an `ObjectPattern` or `ArrayPattern`.

Common situations: Porting JS/TS snippets that rely on destructuring into SDK builder code; extracting fields from an SDK function's return value; unpacking AI subnode parameters; refactoring from Code-node-style JS where destructuring is idiomatic.

Related errors


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