different-ai/openwork · error · InterpreterRuntimeError

for await...of is not supported.

Error message

for await...of is not supported.

What it means

The CodeMode interpreter does not implement the async-iteration form of for...of. evaluateForOfStatement checks the parsed `await` flag on the for...of node and throws immediately before evaluating anything. Async iteration (async generators/streams) is outside the sandbox's supported surface.

Source

Thrown at packages/codemode/src/interpreter/runtime.ts:1076

          }
        }

        if (updateNode) {
          yield* self.evaluateExpression(updateNode)
        }

        if (result.kind === "continue") {
          continue
        }
      }

      return { kind: "none" } satisfies StatementResult
    }).pipe(Effect.ensuring(Effect.sync(() => self.popScope())))
  }

  private evaluateForOfStatement(node: AstNode): Effect.Effect<StatementResult, unknown, R> {
    if (getBoolean(node, "await")) {
      throw new InterpreterRuntimeError("for await...of is not supported.", node)
    }

    const self = this
    return Effect.gen(function* () {
      const left = getNode(node, "left")
      const right = yield* self.evaluateExpression(getNode(node, "right"))
      const body = getNode(node, "body")

      // Arrays iterate in place; strings iterate code points; Maps iterate [key, value]
      // pairs and Sets iterate values over a snapshot (mutation during iteration is safe).
      const iterable = Array.isArray(right) ? right : spreadItems(right)
      if (iterable === undefined) {
        throw new InterpreterRuntimeError("for...of requires an array, string, Map, or Set value in CodeMode.", node)
      }

      let declaration: { readonly pattern: AstNode; readonly mutable: boolean } | undefined
      let assignmentName: string | undefined

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Rewrite the loop to consume a synchronous array: collect results first (via an awaited tool call returning an array), then `for (const x of results)`.
  2. Use `.then`-free patterns: have the tool API return a full data array instead of an async iterable.
  3. If async iteration is essential, run the code outside CodeMode (plain JS execution environment).

Example fix

// before
for await (const chunk of stream) { ... }
// after
const chunks = await readAll(streamTool)
for (const chunk of chunks) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// reject for-await before handing code to CodeMode
if (/for\s+await\s*\(/.test(source)) {
  throw new Error("CodeMode does not support for await...of; collect results into an array first");
}

Try / catch

try {
  await interpret(src);
} catch (e) {
  if (e instanceof InterpreterRuntimeError && e.message.includes("for await")) {
    // fall back to a tool call that returns a complete array
  }
  throw e;
}

Prevention

When it happens

Trigger: Writing `for await (const x of asyncIterable)` in CodeMode source — e.g. iterating an async generator or an async stream.

Common situations: Porting plain JavaScript that consumes async generators or streams into CodeMode scripts; the dialect simply has no async iteration support.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/729863b6e96f468b. Report an issue: GitHub.