{"record":{"id":"1c64631e7e6d56e6","repo":"different-ai/openwork","slug":"for-of-supports-one-declared-binding","errorCode":null,"errorMessage":"for...of supports one declared binding.","messagePattern":"for\\.\\.\\.of supports one declared binding\\.","errorType":"exception","errorClass":"InterpreterRuntimeError","httpStatus":null,"severity":"error","filePath":"packages/codemode/src/interpreter/runtime.ts","lineNumber":1098,"sourceCode":"    return Effect.gen(function* () {\n      const left = getNode(node, \"left\")\n      const right = yield* self.evaluateExpression(getNode(node, \"right\"))\n      const body = getNode(node, \"body\")\n\n      // Arrays iterate in place; strings iterate code points; Maps iterate [key, value]\n      // pairs and Sets iterate values over a snapshot (mutation during iteration is safe).\n      const iterable = Array.isArray(right) ? right : spreadItems(right)\n      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","sourceCodeStart":1080,"sourceCodeEnd":1116,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/codemode/src/interpreter/runtime.ts#L1080-L1116","documentation":"The for...of head may declare exactly one binding per iteration element. If the left side is a VariableDeclaration with more than one declarator (e.g. `for (const a = 1, b = 2 of ...)`), the interpreter throws at the declaration node. Real JS cannot express multiple declarators in a for-of head either; this enforces that and the interpreter's simpler binding model.","triggerScenarios":"A for...of whose left side is a VariableDeclaration whose `declarations` array length !== 1, typically from malformed or hand-written AST-like code.","commonSituations":"Programmatically generated CodeMode ASTs (e.g. by an LLM emitting raw nodes) that accidentally include two declarators; minified/transformed code that merged declarations.","solutions":["Use exactly one declarator: `for (const x of iterable)`.","Destructure in the single binding if you need multiple values: `for (const [a, b] of pairs)`.","Move extra declarations outside the loop."],"exampleFix":"// before (AST with two declarators)\nfor (const a, b of items) ...\n// after\nfor (const [a, b] of items) ...","handlingStrategy":"validation","validationCode":"// AST check before execution\nif (forOfNode.left.type === \"VariableDeclaration\" && forOfNode.left.declarations.length !== 1) {\n  throw new Error(\"for...of head must declare exactly one binding\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  interpret(src);\n} catch (e) {\n  if (e instanceof InterpreterRuntimeError && e.message.includes(\"one declared binding\")) {\n    // fix the AST/code to a single declarator or destructuring\n  }\n  throw e;\n}","preventionTips":["Emit exactly one declarator in for-of heads when generating ASTs.","Use destructuring ([a, b]) to bind multiple values from one element.","Add AST validation in your code generator for loop heads."],"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"}