{"record":{"id":"004cff1b803684c5","repo":"ReactiveX/rxjs","slug":"symbol-asynciterator-must-return-an-object","errorCode":null,"errorMessage":"Symbol.asyncIterator must return an object","messagePattern":"Symbol\\.asyncIterator must return an object","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/observable-polyfill/src/index.ts","lineNumber":369,"sourceCode":"\n  const iterator = iteratorMethod.call(value);\n  if (!isObject(iterator)) {\n    throw new TypeError('Symbol.iterator must return an object');\n  }\n\n  const next = getMethod(iterator, 'next');\n  if (!next) {\n    throw new TypeError('Iterator must define a callable next() method');\n  }\n  return { iterator, next };\n}\n\nfunction getAsyncIteratorRecord(value: object): AsyncIteratorRecord {\n  const asyncIteratorMethod = getMethod(value, Symbol.asyncIterator);\n  if (asyncIteratorMethod) {\n    const iterator = asyncIteratorMethod.call(value);\n    if (!isObject(iterator)) {\n      throw new TypeError('Symbol.asyncIterator must return an object');\n    }\n    return { iterator };\n  }\n\n  return { iterator: getSyncIteratorRecord(value).iterator };\n}\n\nfunction closeSyncIterator(record: SyncIteratorRecord<unknown>, reason: unknown): void {\n  const returnMethod = getMethod(record.iterator, 'return');\n  if (!returnMethod) {\n    return;\n  }\n\n  const result = returnMethod.call(record.iterator, reason);\n  if (!isObject(result)) {\n    throw new TypeError('Iterator return() must return an Object');\n  }\n}","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/ReactiveX/rxjs/blob/54796b38a57e6309f9861e174737479bb3f63f61/packages/observable-polyfill/src/index.ts#L351-L387","documentation":"When Observable.from encounters an object with a Symbol.asyncIterator method, it calls that method and requires the result to be an object (the async iterator). If the call returns a primitive (number, string, undefined, etc.), the polyfill throws this TypeError, mirroring the async-iterator record creation step of the async iteration protocol.","triggerScenarios":"Observable.from(obj) where obj[Symbol.asyncIterator] exists but returns a non-object (e.g. returns undefined because the method lacks a return statement, or returns a Promise or primitive).","commonSituations":"Async generator mocks in tests; objects that declare [Symbol.asyncIterator] but implement it incorrectly; accidental early return in a hand-rolled async iterator; Node streams/web streams wrappers that return the wrong handle.","solutions":["Make [Symbol.asyncIterator]() return an async iterator object — easiest via an async generator: async *[Symbol.asyncIterator]() { ... }.","If delegating, return the other source's iterator: return otherSource[Symbol.asyncIterator]().","Check for a missing return statement in a custom asyncIterator implementation.","Remove the Symbol.asyncIterator property if the object is meant to be a sync iterable."],"exampleFix":"// before\nconst bad = { [Symbol.asyncIterator]() { /* forgot return */ } };\nObservable.from(bad);\n// after\nconst good = { async *[Symbol.asyncIterator]() { yield 1; } };\nObservable.from(good);","handlingStrategy":"validation","validationCode":"const it = (value as any)[Symbol.asyncIterator]?.();\nif (!(it instanceof Object)) throw new Error('asyncIterator must return an object');","typeGuard":"function isAsyncIterable<T>(v: unknown): v is AsyncIterable<T> {\n  return !!v && typeof v === 'object' &&\n    typeof (v as AsyncIterable<T>)[Symbol.asyncIterator] === 'function';\n}","tryCatchPattern":"try { obs = Observable.from(input); } catch (e) { if (e instanceof TypeError && /asyncIterator must return an object/.test(e.message)) { /* skip or replace source */ } else throw e; }","preventionTips":["Implement async iterables as async generators.","Delegate [Symbol.asyncIterator] to a real source instead of hand-writing it.","Unit-test the object returned by [Symbol.asyncIterator].()"],"tags":["async-iterator","symbol-asynciterator","observable-from","typeerror","validation"],"backgroundTag":"invalid-iterator-protocol","analyzedSha":"54796b38a57e6309f9861e174737479bb3f63f61","analyzedAt":"2026-08-28T10:21:27.410Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}