denoland/deno · error · TypeError

could not be iterated because iterator method did not…

Error message

${openContext} could not be iterated because iterator method did not return object, but ${type(iter)}.

What it means

WebIDL async-iterable conversion 'open' step: it calls the stored @@iterator/@@asyncIterator method on the value and requires the returned iterator to be an Object. If a primitive comes back, this TypeError includes the API context (openContext) and the actual type name from webidl's type() ('Undefined', 'String', 'Number', ...).

Solutions

  1. Return an iterator object (usually this) from the @@iterator/@@asyncIterator method
  2. Or delegate: return source[Symbol.asyncIterator]();
  3. Pass a native iterable (Array, Map, Set, ReadableStream) instead of a custom object

Example fix

// before
const body = { [Symbol.asyncIterator]: () => 'not-an-iterator' };
await fetch(url, { body });

// after
const body = { async *[Symbol.asyncIterator]() { yield 'chunk'; } };
await fetch(url, { body });
Defensive patterns

Strategy: validation

Validate before calling

function assertOpenable(v: unknown) {
  const m = (v as any)?.[Symbol.asyncIterator] ?? (v as any)?.[Symbol.iterator];
  if (typeof m !== 'function') return; // absence is a different error
  const iter = m.call(v);
  if (typeof iter !== 'object' || iter === null) {
    throw new TypeError('iterator method must return an iterator object');
  }
}

Type guard

const isAsyncIterable = (v: unknown): v is AsyncIterable<unknown> =>
  v != null && typeof (v as Record<PropertyKey, unknown>)[Symbol.asyncIterator] === 'function';

Prevention

When it happens

Trigger: fetch(url, { body: { [Symbol.asyncIterator]: () => 'stream' } }) or any Deno API taking an async sequence where the iterator method returns a primitive instead of an iterator object.

Common situations: Writing [Symbol.asyncIterator]() { return this.items } where items is a string/number; async-iterator methods that return a value instead of this or an iterator; confusing 'the method returns the iterator' with 'the method returns the data'.

Related errors


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

Appendix: source

Thrown at ext/webidl/00_webidl.js:1126

          context,
        );
      }
      sequenceType = "sync";
    }

    return {
      // Fields used by extractBody / callers.
      value: V,
      object: V,
      method,
      type: sequenceType,
      [AsyncSequence]: AsyncSequence,
      // https://webidl.spec.whatwg.org/#async-sequence-open
      open(openContext = context) {
        // 1. Let iterator be ? GetIteratorFromMethod(object, method).
        const iter = FunctionPrototypeCall(method, V);
        if (type(iter) !== "Object") {
          throw new TypeError(
            `${openContext} could not be iterated because iterator method did not return object, but ${
              type(iter)
            }.`,
          );
        }

        // 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() {

View on GitHub (pinned to f7822238ca)