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
- 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)`.
- Use `.then`-free patterns: have the tool API return a full data array instead of an async iterable.
- 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
- Never write for await in CodeMode scripts.
- Have tools return full arrays instead of async iterables.
- Lint generated CodeMode code for `for await` before execution.
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
- Expected '${key}' to be a boolean.
- Failed to parse script as a Program node.
- String.${name} expects argument ${index + 1} to be a number.
- String.normalize expects the form "NFC", "NFD", "NFKC", or "
- String.replaceAll requires a regular expression with the glo
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/729863b6e96f468b.
Report an issue: GitHub.