{"record":{"id":"3d8cb4002baae530","repo":"n8n-io/n8n","slug":"unsupported-syntax-dynamic-property-assignment","errorCode":null,"errorMessage":"Unsupported syntax: 'Dynamic property assignment' is not allowed in SDK code","messagePattern":"Unsupported syntax: 'Dynamic property assignment' is not allowed in SDK code","errorType":"exception","errorClass":"UnsupportedNodeError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts","lineNumber":739,"sourceCode":"\t\t}\n\n\t\tconst obj = this.evaluate(node.left.object);\n\n\t\tif (obj === null || obj === undefined) {\n\t\t\tthrow new InterpreterError(\n\t\t\t\t`Cannot assign property on ${String(obj)}`,\n\t\t\t\tnode.loc ?? undefined,\n\t\t\t\tthis.sourceCode,\n\t\t\t);\n\t\t}\n\n\t\tlet propName: string | number;\n\t\tif (node.left.property.type === 'Identifier' && !node.left.computed) {\n\t\t\tpropName = node.left.property.name;\n\t\t} else if (node.left.property.type === 'Literal') {\n\t\t\tpropName = node.left.property.value as string | number;\n\t\t} else {\n\t\t\tthrow new UnsupportedNodeError(\n\t\t\t\t'Dynamic property assignment',\n\t\t\t\tnode.left.property.loc ?? undefined,\n\t\t\t\tthis.sourceCode,\n\t\t\t);\n\t\t}\n\n\t\tconst value = this.evaluate(node.right);\n\t\t(obj as Record<string | number, unknown>)[propName] = value;\n\t\treturn value;\n\t}\n\n\t/**\n\t * Get set of declared variable names.\n\t */\n\tprivate getVariableNames(): Set<string> {\n\t\treturn new Set(this.variables.keys());\n\t}\n}","sourceCodeStart":721,"sourceCodeEnd":757,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts#L721-L757","documentation":"Thrown by visitAssignmentExpression when the left-hand property is neither a non-computed Identifier nor a Literal. This rejects computed/dynamic property keys in assignments like `obj[someVar] = value` or `obj[expr] = value`. The interpreter only allows statically-known property names for security and predictability.","triggerScenarios":"SDK code containing `obj[variableName] = value`, `obj[computeKey()] = value`, or any bracket-notation assignment where the key is not a string/number literal. Template-literal keys (`obj[`key`] = value`) also fail because TemplateLiteral is not a Literal.","commonSituations":"Pasting generic JavaScript that builds objects dynamically; code generators that emit bracket-notation updates; refactoring from a loop into SDK code without flattening.","solutions":["Use static dot notation: `obj.fixedName = value`.","Use a string-literal key in brackets: `obj['fixedKey'] = value` (Literal is allowed).","Build the object in one shot with an object literal instead of mutating dynamic keys: `const obj = { [computedKey]: value }` — but note computed keys in literals are also restricted; prefer a fixed structure or move dynamic logic to a Code node."],"exampleFix":"// before\nconst key = dynamicKey();\nobj[key] = value;\n\n// after\nobj.fixedKey = value;\n// or, if the key is a known constant string:\nobj['fixedKey'] = value;","handlingStrategy":"validation","validationCode":"import { parseSDKCode } from '@n8n/workflow-sdk/ast-interpreter/parser';\n\nfunction findDynamicAssignmentKeys(code: string): string[] {\n  const issues: string[] = [];\n  const ast = parseSDKCode(code);\n  JSON.stringify(ast, (k, v) => {\n    if (v?.type === 'AssignmentExpression' && v.left?.type === 'MemberExpression' && v.left.computed) {\n      if (v.left.property?.type !== 'Literal') {\n        issues.push(`Dynamic assignment key at line ${v.loc?.start.line}: use a static name or literal`);\n      }\n    }\n    return v;\n  });\n  return issues;\n}","typeGuard":"function isStaticKey(prop: unknown): boolean {\n  if (!prop || typeof prop !== 'object') return false;\n  const t = (prop as { type?: string }).type;\n  return t === 'Identifier' || t === 'Literal';\n}","tryCatchPattern":"import { interpretSDKCode } from '@n8n/workflow-sdk/ast-interpreter/interpreter';\nimport { UnsupportedNodeError } from '@n8n/workflow-sdk/ast-interpreter/errors';\n\ntry {\n  interpretSDKCode(code, sdkFunctions);\n} catch (e) {\n  if (e instanceof UnsupportedNodeError && /Dynamic property assignment/.test(e.message)) {\n    // instruct user to replace obj[var] = v with obj.fixedKey = v\n  }\n  throw e;\n}","preventionTips":["Ban bracket-notation assignment in SDK code via a lint rule; require dot notation or string-literal keys.","Build objects in one shot with literals rather than mutating dynamic keys.","Run a static AST pass rejecting computed MemberExpression on the left of '='."],"tags":["sdk","ast-interpreter","dynamic-access","assignment"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}