{"record":{"id":"c34e53ff26c44563","repo":"mongodb/node-mongodb-native","slug":"changestream-cannot-be-used-as-an-eventemitter-aft","errorCode":null,"errorMessage":"ChangeStream cannot be used as an EventEmitter after being used as an iterator","messagePattern":"ChangeStream cannot be used as an EventEmitter after being used as an iterator","errorType":"exception","errorClass":"MongoAPIError","httpStatus":null,"severity":"error","filePath":"src/change_stream.ts","lineNumber":880,"sourceCode":"   *\n   * NOTE: When using a Stream to process change stream events, the stream will\n   * NOT automatically resume in the case a resumable error is encountered.\n   *\n   * @throws MongoChangeStreamError if the underlying cursor or the change stream is closed\n   */\n  stream(): Readable & AsyncIterable<TChange> {\n    if (this.closed) {\n      throw new MongoChangeStreamError(CHANGESTREAM_CLOSED_ERROR);\n    }\n\n    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  /**","sourceCodeStart":862,"sourceCodeEnd":898,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/change_stream.ts#L862-L898","documentation":"Thrown when a 'change' event listener is added to a ChangeStream that has already been used as an async iterator (via next(), hasNext(), tryNext(), or for-await-of). The ChangeStream enforces a single mode: either EventEmitter-style (event listeners) or iterator-style (async iteration). Switching from iterator to emitter is forbidden. This is a MongoAPIError.","triggerScenarios":"First calling changeStream.next() or using for-await-of, then later calling changeStream.on('change', callback). The mode is set to 'iterator' by the first iterator-style call and cannot revert to 'emitter'.","commonSituations":"Refactoring code from for-await-of to event-based listening without creating a new change stream; mixing two consumer patterns in the same module; shared change stream instance used by both an iterator consumer and an event consumer.","solutions":["Choose one consumption pattern (events or iterator) per ChangeStream instance and stick with it","If you need to switch patterns, close the current change stream and create a new one with the same options/resume token","Use the resume token from the closed stream to start the new one at the correct position"],"exampleFix":"// before\nconst doc = await changeStream.next(); // sets iterator mode\nchangeStream.on('change', handler); // throws\n\n// after\nconst token = changeStream.resumeToken;\nawait changeStream.close();\nconst newStream = collection.watch(pipeline, { resumeAfter: token });\nnewStream.on('change', handler);","handlingStrategy":"validation","validationCode":"// Decide on one consumption mode before using the change stream\n// Option A: events only\nchangeStream.on('change', handler);\n// Option B: iterator only\nfor await (const change of changeStream) { ... }\n// Do NOT mix the two on the same instance.","typeGuard":null,"tryCatchPattern":"try {\n  changeStream.on('change', handler);\n} catch (error) {\n  if (error instanceof MongoAPIError && error.message.includes('EventEmitter')) {\n    // Stream was used as iterator; create a new stream for event mode\n    const token = changeStream.resumeToken;\n    const newStream = collection.watch(pipeline, { resumeAfter: token });\n    newStream.on('change', handler);\n  }\n}","preventionTips":["Choose one consumption pattern (events or iterator) per ChangeStream instance at design time","Document the chosen pattern in code comments to prevent other developers from mixing modes","If you need both patterns, use separate ChangeStream instances"],"tags":["change-stream","api-misuse","event-emitter"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}