{"record":{"id":"921d2a923fedbe50","repo":"denoland/deno","slug":"the-iterator-return-method-must-return-an-object","errorCode":null,"errorMessage":"The iterator.return() method must return an object","messagePattern":"The iterator\\.return\\(\\) method must return an object","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/webidl/00_webidl.js","lineNumber":1064,"sourceCode":"      // AsyncFromSyncIteratorContinuation awaits the yielded value so that\n      // sync sources of promises (e.g. arrays of Promises) unwrap.\n      return {\n        done: false,\n        value: await iterResult.value,\n      };\n    },\n    async return(reason) {\n      const returnMethod = getMethod(syncIterator, \"return\");\n      if (returnMethod === undefined) {\n        return { done: true, value: undefined };\n      }\n      const returnResult = await FunctionPrototypeCall(\n        returnMethod,\n        syncIterator,\n        reason,\n      );\n      if (type(returnResult) !== \"Object\") {\n        throw new TypeError(\n          \"The iterator.return() method must return an object\",\n        );\n      }\n      return { done: true, value: undefined };\n    },\n    [SymbolAsyncIterator]() {\n      return this;\n    },\n  };\n}\n\nconst AsyncSequence = Symbol(\"[[asyncSequence]]\");\n\n// https://webidl.spec.whatwg.org/#js-async-iterable\n// https://webidl.spec.whatwg.org/#async-sequence-open\nfunction createAsyncSequenceConverter(converter) {\n  return function (\n    V,","sourceCodeStart":1046,"sourceCodeEnd":1082,"githubUrl":"https://github.com/denoland/deno/blob/f7822238cab635a3a19f99f493f675fa81a7f9d8/ext/webidl/00_webidl.js#L1046-L1082","documentation":"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.","triggerScenarios":"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.","commonSituations":"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().","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 }"],"exampleFix":"// before\n[Symbol.iterator]() {\n  return { next: () => ({ done: false, value: 1 }), return() { cleanup(); } };\n}\n\n// after\n[Symbol.iterator]() {\n  return { next: () => ({ done: false, value: 1 }), return() { cleanup(); return { done: true }; } };\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":"interface CloseableIterator<T> extends Iterator<T> {\n  return?(value?: unknown): IteratorResult<T>;\n}\n// Custom iterators typed as CloseableIterator<T> force return() to yield an object.","tryCatchPattern":null,"preventionTips":["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"],"tags":["webidl","iterator","cleanup","early-termination","typeerror"],"backgroundTag":"iterator-return-returns-non-object","analyzedSha":"f7822238cab635a3a19f99f493f675fa81a7f9d8","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}