denoland/deno · error · TypeError
${openContext} failed to iterate next value because the next
Error message
${openContext} failed to iterate next value because the next() method did not return an object, but ${type(iterResult)}. What it means
While iterating a WebIDL async sequence, every awaited result of the captured next() method must be an Object ({ done, value }). This TypeError names the API context (openContext) and the offending type (e.g. 'Number') when next() resolves to a primitive.
Source
Thrown at ext/webidl/00_webidl.js:1150
// 2. If type is "sync", set iterator to CreateAsyncFromSyncIterator(iterator).
const asyncIterator = sequenceType === "sync"
? createAsyncFromSyncIterator(iter)
: iter;
// Capture nextMethod per Iterator Record semantics.
const nextMethod = asyncIterator.next;
return {
// https://webidl.spec.whatwg.org/#async-iterator-get-next-value
// Exposed as an async iterator protocol shape for callers.
async next() {
const iterResult = await FunctionPrototypeCall(
nextMethod,
asyncIterator,
);
if (type(iterResult) !== "Object") {
throw new TypeError(
`${openContext} failed to iterate next value because the next() method did not return an object, but ${
type(iterResult)
}.`,
);
}
if (iterResult.done) {
return { done: true, value: undefined };
}
const iterValue = converter(
iterResult.value,
`${openContext} failed to iterate next value`,
"The value returned from the next() method",
opts,
);
return { done: false, value: iterValue };View on GitHub (pinned to f7822238ca)
Solutions
- Wrap every result: return { done: false, value } and return { done: true } at the end
- Replace the manual iterator with an async generator (async function*)
- Read the openContext in the message to identify which API argument failed
Example fix
// before
const body = { [Symbol.asyncIterator]: () => ({ next: async () => 'chunk' }) };
// after
const body = { async *[Symbol.asyncIterator]() { yield 'chunk'; } }; Defensive patterns
Strategy: validation
Validate before calling
const it = body[Symbol.asyncIterator]();
const r = await it.next();
if (typeof r !== 'object' || r === null) {
throw new TypeError('async next() must resolve to { done, value }');
} Type guard
const isAsyncIteratorResult = (r: unknown): r is IteratorResult<unknown> => typeof r === 'object' && r !== null;
Prevention
- Async iterators resolve to IteratorResult objects, never raw values
- Use async generators instead of hand-written next()
- Type custom async iterators as AsyncIterator<T>
When it happens
Trigger: A custom async iterator with next: async () => 42 or next() { return Promise.resolve('x'); } used as an async-sequence input (e.g. fetch body); next() returning undefined after exhaustion.
Common situations: Async next() implementations returning the value directly instead of { value, done }; wrapper/mapping code that transforms the iterator result; returning done: true as a bare boolean.
Related errors
- ${name} is not a function
- The iterator.next() method must return an object
- ${openContext} failed to close iterator because the return()
- Cannot convert a BigInt value to a number
- Cannot convert a Symbol value to a string
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/8f43c343b5e55766.
Report an issue: GitHub.