denoland/deno · error · TypeError
The iterator.return() method must return an object
Error message
The iterator.return() method must return an object
What it means
The manual async-from-sync wrapper's return() runs when the consumer closes the iterator early (break, throw, cancellation). It looks up the sync iterator's optional return() via getMethod; if the method exists, its (awaited) result must be an Object or this TypeError is thrown.
Source
Thrown at ext/webidl/00_webidl.js:1064
// AsyncFromSyncIteratorContinuation awaits the yielded value so that
// sync sources of promises (e.g. arrays of Promises) unwrap.
return {
done: false,
value: await iterResult.value,
};
},
async return(reason) {
const returnMethod = getMethod(syncIterator, "return");
if (returnMethod === undefined) {
return { done: true, value: undefined };
}
const returnResult = await FunctionPrototypeCall(
returnMethod,
syncIterator,
reason,
);
if (type(returnResult) !== "Object") {
throw new TypeError(
"The iterator.return() method must return an object",
);
}
return { done: true, value: undefined };
},
[SymbolAsyncIterator]() {
return this;
},
};
}
const AsyncSequence = Symbol("[[asyncSequence]]");
// https://webidl.spec.whatwg.org/#js-async-iterable
// https://webidl.spec.whatwg.org/#async-sequence-open
function createAsyncSequenceConverter(converter) {
return function (
V,View on GitHub (pinned to f7822238ca)
Solutions
- Return an object from return(): return { done: true };
- Or omit return() entirely - an absent return method is skipped, not an error
- When delegating to an inner iterator, return its result object: return inner.return?.() ?? { done: true }
Example fix
// before
[Symbol.iterator]() {
return { next: () => ({ done: false, value: 1 }), return() { cleanup(); } };
}
// after
[Symbol.iterator]() {
return { next: () => ({ done: false, value: 1 }), return() { cleanup(); return { done: true }; } };
} Defensive patterns
Strategy: validation
Type guard
interface CloseableIterator<T> extends Iterator<T> {
return?(value?: unknown): IteratorResult<T>;
}
// Custom iterators typed as CloseableIterator<T> force return() to yield an object. Prevention
- Always return { done: true } from return()
- Use generators - their return() is spec-correct
- Test early-exit paths (break, abort) with custom iterators, not only happy paths
When it happens
Trigger: A custom sync iterator used as async-iterable input with a cleanup return() that returns a primitive or nothing: return() { cleanup(); } (implicit undefined), return: () => null, or return: () => true - and the consumer then terminates iteration early.
Common situations: Adding cleanup hooks that forget to return a value; porting iterator code where return() was void; returning a boolean status or a resource id (number) from return().
Related errors
- The iterator.next() method must return an object
- ${openContext} could not be iterated because iterator method
- ${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/921d2a923fedbe50.
Report an issue: GitHub.