{"record":{"id":"32ea2ad934675f1c","repo":"mongodb/node-mongodb-native","slug":"changestream-cannot-be-used-as-an-iterator-after-b","errorCode":null,"errorMessage":"ChangeStream cannot be used as an iterator after being used as an EventEmitter","messagePattern":"ChangeStream cannot be used as an iterator after being used as an EventEmitter","errorType":"exception","errorClass":"MongoAPIError","httpStatus":null,"severity":"error","filePath":"src/change_stream.ts","lineNumber":891,"sourceCode":"    return this.cursor.stream();\n  }\n\n  /** @internal */\n  private _setIsEmitter(): void {\n    if (this.mode === 'iterator') {\n      // TODO(NODE-3485): Replace with MongoChangeStreamModeError\n      throw new MongoAPIError(\n        'ChangeStream cannot be used as an EventEmitter after being used as an iterator'\n      );\n    }\n    this.mode = 'emitter';\n  }\n\n  /** @internal */\n  private _setIsIterator(): void {\n    if (this.mode === 'emitter') {\n      // TODO(NODE-3485): Replace with MongoChangeStreamModeError\n      throw new MongoAPIError(\n        'ChangeStream cannot be used as an iterator after being used as an EventEmitter'\n      );\n    }\n    this.mode = 'iterator';\n  }\n\n  /**\n   * Create a new change stream cursor based on self's configuration\n   * @internal\n   */\n  private _createChangeStreamCursor(\n    options: ChangeStreamOptions | ChangeStreamCursorOptions\n  ): ChangeStreamCursor<TSchema, TChange> {\n    const changeStreamStageOptions: Document = filterOutOptions(options);\n    if (this.type === CHANGE_DOMAIN_TYPES.CLUSTER) {\n      changeStreamStageOptions.allChangesForCluster = true;\n    }\n    const pipeline = [{ $changeStream: changeStreamStageOptions }, ...this.pipeline];","sourceCodeStart":873,"sourceCodeEnd":909,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/change_stream.ts#L873-L909","documentation":"Thrown when an iterator-style method (next(), hasNext(), tryNext(), or for-await-of) is called on a ChangeStream that has already been used as an EventEmitter (a 'change' listener was attached). The ChangeStream enforces a single consumption mode and switching from emitter to iterator is forbidden. This is a MongoAPIError.","triggerScenarios":"First calling changeStream.on('change', callback) (which sets emitter mode via _setIsEmitter), then later calling changeStream.next() or using for-await-of on the same instance.","commonSituations":"Refactoring from event listeners to async iteration without recreating the stream; shared change stream instances across modules where one attaches events and another iterates; code that attaches a temporary listener then tries to iterate.","solutions":["Choose one consumption pattern per ChangeStream instance from the start","If you must switch, create a new change stream using the resume token from the previous one","Remove all 'change' listeners and close the stream before creating a new iterator-based stream"],"exampleFix":"// before\nchangeStream.on('change', handler); // sets emitter mode\nconst doc = await changeStream.next(); // throws\n\n// after\nconst token = changeStream.resumeToken;\nawait changeStream.close();\nconst newStream = collection.watch(pipeline, { resumeAfter: token });\nfor await (const change of newStream) {\n  handler(change);\n}","handlingStrategy":"validation","validationCode":"// Decide on one consumption mode before using the change stream\n// If events are attached, do not call iterator methods\nif (changeStream.listenerCount('change') > 0) {\n  throw new Error('Cannot use iterator methods after attaching change listeners');\n}\nconst doc = await changeStream.next();","typeGuard":null,"tryCatchPattern":"try {\n  const doc = await changeStream.next();\n} catch (error) {\n  if (error instanceof MongoAPIError && error.message.includes('iterator')) {\n    // Stream is in emitter mode; create new stream for iteration\n    const token = changeStream.resumeToken;\n    const newStream = collection.watch(pipeline, { resumeAfter: token });\n    doc = await newStream.next();\n  }\n}","preventionTips":["Choose one consumption pattern per ChangeStream instance from the start","If switching from events to iteration, close and recreate the stream with a resume token","Avoid sharing change stream instances across modules that use different consumption patterns"],"tags":["change-stream","api-misuse","async-iteration"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}