{"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/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/change_stream.ts#L873-L909","documentation":"Inverse of error 21: _setIsIterator() throws this MongoAPIError when you attempt to consume the ChangeStream with for-await after it has already been used as an EventEmitter (on('change', ...)). The driver tracks mode to prevent the cursor from being driven by two different mechanisms at once.","triggerScenarios":"First registering `changeStream.on('change', cb)` (which starts emitter-mode pumping via _streamEvents), then later running `for await (const change of changeStream)` on the same instance.","commonSituations":"Layered code where a base module attaches listeners and a caller later tries to iterate; replacing a listener with iteration without removing the listener; integration tests that exercise both APIs on one instance.","solutions":["Stop using event listeners on this instance and consume it solely via for-await, or vice versa.","Spin up a second ChangeStream via collection.watch() dedicated to the iterator consumption.","Remove the .on('change') registration (and call close() if needed) before creating a new instance to iterate."],"exampleFix":"// before\ncs.on('change', handle);\nfor await (const change of cs) {} // throws\n\n// after\ncs.on('change', handle); // emitter mode only","handlingStrategy":"validation","validationCode":"// Application-level: do not register listeners on instances you intend to iterate.\nconst MODE = Symbol('mode');\nfunction iterate(cs) {\n  if (cs.listenerCount('change') > 0) throw new Error('already in emitter mode');\n}","typeGuard":"// No public mode field; model it in your own wrapper.\ninterface ManagedChangeStream { mode: 'emitter' | 'iterator' | null; }","tryCatchPattern":"try {\n  for await (const c of cs) handle(c);\n} catch (err) {\n  if (err instanceof MongoAPIError && /iterator after being used as an EventEmitter/.test(err.message)) {\n    // open a fresh change stream for iteration\n  } else throw err;\n}","preventionTips":["Choose for-await OR event listeners up front and do not mix them.","If a library attaches listeners, give it its own ChangeStream instance.","Code-review change-stream usage for accidental dual-mode access."],"tags":["change-streams","api-misuse","eventemitter","async-iterator"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}