{"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/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/change_stream.ts#L862-L898","documentation":"A ChangeStream can be consumed in exactly one mode: EventEmitter (on('change', ...)) or async iterator (for-await). The internal _setIsEmitter() throws this MongoAPIError when you attach event listeners after the stream has already started being consumed with for-await-of. The mode is sticky and mutually exclusive to prevent two concurrent consumption loops racing on the same cursor.","triggerScenarios":"Running `for await (const change of changeStream)` and then, later, calling `changeStream.on('change', ...)` (or any event listener registration that triggers _streamEvents) on the same instance.","commonSituations":"Migrating code from event style to iterator style piecemeal; mixing a helper that iterates with another that listens; refactoring that leaves a stray .on('change') call after introducing a for-await loop.","solutions":["Pick one consumption style per ChangeStream instance and remove the other.","If you need both behaviors, create two separate ChangeStream instances via two collection.watch() calls.","Refactor so iteration results are pushed into your own EventEmitter rather than reusing the driver's."],"exampleFix":"// before\nfor await (const change of cs) { handle(change); }\ncs.on('change', handle); // throws\n\n// after\nfor await (const change of cs) { handle(change); }","handlingStrategy":"validation","validationCode":"// Enforce one consumption mode per instance at the call site\nfunction assertEmitterMode(cs) {\n  if (cs.isClosed || /* iterator started */ false) throw new Error('already iterating');\n}","typeGuard":"type ChangeStreamMode = 'emitter' | 'iterator' | null;\n// Mode is internal; treat it as an application-level invariant: one style per instance.","tryCatchPattern":"try {\n  cs.on('change', handler);\n} catch (err) {\n  if (err instanceof MongoAPIError && /EventEmitter after being used as an iterator/.test(err.message)) {\n    // create a new ChangeStream for emitter use\n  } else throw err;\n}","preventionTips":["Standardize on one consumption pattern per change stream across your codebase.","Document on each ChangeStream instance which mode it is intended for.","Avoid mixing helper libraries that assume different modes on the same instance."],"tags":["change-streams","api-misuse","eventemitter","async-iterator"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}