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
- Check that the object on the left side of the assignment is declared and non-null before the assignment line.
- Replace `x.y = value` with construction via an object literal: `const x = { y: value };`.
- 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
- Always initialize objects with a literal (`const x = {}`) before assigning properties onto them.
- Use object-literal construction (`const x = { y: 1 }`) rather than declare-then-mutate.
- Track declared identifiers in a Set and statically verify assignment targets reference a declared name.
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
- Unsupported syntax: 'Dynamic property assignment' is not all
- VectorStore "${this.name}" requires an embedding model — set
- topK must be an integer >= 1, got ${k}
- Unsupported syntax: '${nodeType}' is not allowed in SDK code
- '${node.kind}' declarations are not allowed. Use 'const' onl
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/321083b06c243c4e.
Report an issue: GitHub.