{"record":{"id":"413b79fafe62f855","repo":"different-ai/openwork","slug":"unsupported-for-of-binding","errorCode":null,"errorMessage":"Unsupported for...of binding.","messagePattern":"Unsupported for\\.\\.\\.of binding\\.","errorType":"exception","errorClass":"InterpreterRuntimeError","httpStatus":null,"severity":"error","filePath":"packages/codemode/src/interpreter/runtime.ts","lineNumber":1106,"sourceCode":"      if (iterable === undefined) {\n        throw new InterpreterRuntimeError(\"for...of requires an array, string, Map, or Set value in CodeMode.\", node)\n      }\n\n      let declaration: { readonly pattern: AstNode; readonly mutable: boolean } | undefined\n      let assignmentName: string | undefined\n\n      if (left.type === \"VariableDeclaration\") {\n        const declarations = getArray(left, \"declarations\")\n        if (declarations.length !== 1) {\n          throw new InterpreterRuntimeError(\"for...of supports one declared binding.\", left)\n        }\n\n        const declarator = asNode(declarations[0], \"declarations[0]\")\n        declaration = { pattern: getNode(declarator, \"id\"), mutable: getString(left, \"kind\") !== \"const\" }\n      } else if (left.type === \"Identifier\") {\n        assignmentName = getString(left, \"name\")\n      } else {\n        throw new InterpreterRuntimeError(\"Unsupported for...of binding.\", left)\n      }\n\n      for (const value of iterable) {\n        if (declaration) {\n          self.pushScope()\n          yield* self.declarePattern(declaration.pattern, value, declaration.mutable, left)\n        } else if (assignmentName) {\n          self.setIdentifierValue(assignmentName, value, left)\n        }\n\n        const result = yield* self.evaluateStatement(body).pipe(\n          Effect.ensuring(\n            Effect.sync(() => {\n              if (declaration) self.popScope()\n            }),\n          ),\n        )\n","sourceCodeStart":1088,"sourceCodeEnd":1124,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/codemode/src/interpreter/runtime.ts#L1088-L1124","documentation":"The for...of left side must be either a single VariableDeclaration or a plain Identifier (assignment to an existing variable). Any other left-side node kind (member expression like `obj.x`, complex patterns beyond the supported ones, etc.) throws this error at the left node. The interpreter implements only these two binding forms.","triggerScenarios":"`for (obj.key of items)`, `for (arr[0] of items)`, or any AST left node that is neither VariableDeclaration nor Identifier.","commonSituations":"Porting JS that assigns to an object property per iteration; LLM-generated ASTs using unsupported node kinds for the loop target.","solutions":["Declare a loop variable, then assign to the member inside the body: `for (const v of items) { obj.key = v; }`.","Use an existing plain variable as the loop target instead of a property path.","If a pattern is needed, keep it to destructuring supported by declarePattern inside a single VariableDeclaration."],"exampleFix":"// before\nfor (obj.key of items) { ... }\n// after\nfor (const v of items) { obj.key = v; }","handlingStrategy":"validation","validationCode":"// AST check before execution\nconst t = forOfNode.left.type;\nif (t !== \"VariableDeclaration\" && t !== \"Identifier\") {\n  throw new Error(\"for...of target must be a declaration or identifier\");\n}","typeGuard":"const isValidForOfLeft = (n: AstNode): boolean =>\n  n.type === \"Identifier\" ||\n  (n.type === \"VariableDeclaration\" && Array.isArray(n.declarations) && n.declarations.length === 1);","tryCatchPattern":"try {\n  interpret(src);\n} catch (e) {\n  if (e instanceof InterpreterRuntimeError && e.message.includes(\"Unsupported for...of binding\")) {\n    // rewrite to declare + in-body assignment\n  }\n  throw e;\n}","preventionTips":["Assign to object properties inside the loop body, not the head.","Restrict generated loop heads to Identifier or single-declarator declarations.","Validate AST loop nodes before invoking the interpreter."],"tags":["codemode","interpreter","for-of","syntax"],"backgroundTag":"invalid-loop-binding","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}