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

  1. Wrap every result: return { done: false, value } and return { done: true } at the end
  2. Replace the manual iterator with an async generator (async function*)
  3. 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

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


AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20). Data as JSON: /api/errors/8f43c343b5e55766. Report an issue: GitHub.