n8n-io/n8n · error · InterpreterError

Cannot assign property on ${String(obj)}

Error message

Cannot assign property on ${String(obj)}

What it means

Thrown by visitAssignmentExpression after evaluating `node.left.object` to a value that is null or undefined. The interpreter then refuses to set a property on it (would be a TypeError at runtime). This is a runtime evaluation error inside the safe interpreter, not a static syntax rejection.

Source

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

				node.loc ?? undefined,
				this.sourceCode,
			);
		}

		validateMemberExpression(node.left, this.sourceCode);

		if (node.left.object.type === 'Super') {
			throw new UnsupportedNodeError(
				'super keyword is not supported in SDK code',
				node.left.object.loc ?? undefined,
				this.sourceCode,
			);
		}

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

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

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

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Check that the object on the left side of the assignment is declared and non-null before the assignment line.
  2. Replace `x.y = value` with construction via an object literal: `const x = { y: value };`.
  3. If assigning onto an SDK builder result, verify the builder function (workflow/node/trigger) actually returns an object — don't reassign internal fields; use the builder's chained methods instead.

Example fix

// before
const cfg = getMaybeUndef();
cfg.timeout = 30;

// after
const raw = getMaybeUndef();
const cfg = { ...raw, timeout: 30 };
Defensive patterns

Strategy: validation

Validate before calling

// Static check: every assignment target's object must be a declared identifier or a call chain
import { parseSDKCode } from '@n8n/workflow-sdk/ast-interpreter/parser';

function findUnsafeAssignments(code: string, declared: Set<string>): string[] {
  const issues: string[] = [];
  const ast = parseSDKCode(code);
  JSON.stringify(ast, (k, v) => {
    if (v?.type === 'AssignmentExpression' && v.left?.type === 'MemberExpression') {
      const obj = v.left.object;
      if (obj.type === 'Identifier' && !declared.has(obj.name)) {
        issues.push(`Possible null/undefined assignment target '${obj.name}' at line ${v.loc?.start.line}`);
      }
    }
    return v;
  });
  return issues;
}

Type guard

function isNonNullObject(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null;
}

Try / catch

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

try {
  interpretSDKCode(code, sdkFunctions);
} catch (e) {
  if (e instanceof InterpreterError && /Cannot assign property on/.test(e.message)) {
    // Tell user to initialize the object before assigning a property onto it
  }
  throw e;
}

Prevention

When it happens

Trigger: SDK code like `foo.bar = 1` where `foo` evaluates to null or undefined at interpretation time (e.g., `foo` was never declared/assigned, or was explicitly set to null). Also reachable if an SDK function returns undefined and you then assign a property on the result.

Common situations: Typo in a variable name; referencing a variable before its declaration line; chaining `.parameters()` on a node() call that returned undefined due to wrong usage; assigning onto the result of a function that doesn't return an object.

Related errors


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