n8n-io/n8n · error · UnsupportedNodeError

Unsupported syntax: 'Dynamic property access' is not allowed

Error message

Unsupported syntax: 'Dynamic property access' is not allowed in SDK code

What it means

In a member expression for property access, the property must be either a static `Identifier` with `!node.computed` (`obj.name`) or a `Literal` (`obj["name"]`, `arr[0]`). Any other property node type throws `UnsupportedNodeError` at interpreter.ts:342. This complements `validateMemberExpression` (which blocks computed access with non-literals via `SecurityError`) by catching any AST shape that reaches the property-name extraction without being an Identifier or Literal.

Source

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

		const obj = this.evaluate(node.object);

		if (obj === null || obj === undefined) {
			throw new InterpreterError(
				`Cannot access property on ${obj}`,
				node.loc ?? undefined,
				this.sourceCode,
			);
		}

		// Get property name
		let propName: string | number;
		if (node.property.type === 'Identifier' && !node.computed) {
			propName = node.property.name;
		} else if (node.property.type === 'Literal') {
			propName = node.property.value as string | number;
		} else {
			throw new UnsupportedNodeError(
				'Dynamic property access',
				node.property.loc ?? undefined,
				this.sourceCode,
			);
		}

		return (obj as Record<string | number, unknown>)[propName];
	}

	/**
	 * Visit an object expression.
	 */
	private visitObjectExpression(node: ESTree.ObjectExpression): Record<string, unknown> {
		const result: Record<string, unknown> = {};

		for (const prop of node.properties) {
			if (prop.type === 'SpreadElement') {
				// Handle spread: { ...obj }

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Use a static property name: `obj.name` or `obj['name']` (string literal)
  2. Use a numeric literal for array index: `arr[0]`
  3. Move dynamic field selection to a Code node

Example fix

// before
const val = obj[key]; // key is a variable

// after
const val = obj.fixedName; // or obj['fixedName']
Defensive patterns

Strategy: validation

Validate before calling

// Detect computed property access with non-literal keys
function hasDynamicPropertyAccess(code: string): boolean {
  const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });
  let found = false;
  walk(ast, (node) => {
    if (
      node.type === 'MemberExpression' &&
      node.computed &&
      node.property.type !== 'Literal'
    ) {
      found = true;
    }
  });
  return found;
}

Try / catch

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

try {
  interpretSDKCode(sdkCode, sdkFunctions);
} catch (e) {
  if (e instanceof UnsupportedNodeError && e.message.includes('Dynamic property access')) {
    // instruct user to use static property names or literal keys
  }
  throw e;
}

Prevention

When it happens

Trigger: Writing `obj[expression]` where the property is a non-literal — though most computed access is caught earlier by `validateMemberExpression` at line 314. This throw at line 342 catches edge cases where the property node type is something unexpected (e.g., a `TemplateLiteral` key).

Common situations: Dynamic property lookup with runtime-computed keys; template-literal keys (`obj[`${field}`]`); porting code that selects fields dynamically.

Related errors


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