mongodb/node-mongodb-native · error · MongoChangeStreamError
ChangeStream is closed
Error message
ChangeStream is closed
What it means
Thrown by ChangeStream.stream() when the change stream has already been closed (via close() or because the underlying cursor closed). The stream() method returns a Readable for low-level streaming access, but once closed no new stream can be obtained. This is a MongoChangeStreamError.
Solutions
- Check changeStream.closed before calling stream() and create a new change stream if needed
- Do not mix for-await-of iteration with stream() on the same ChangeStream instance
- Create a fresh change stream via collection.watch() if you need to resume after closure
Example fix
// before
const stream = changeStream.stream();
// ... later after close ...
const stream2 = changeStream.stream(); // throws
// after
if (changeStream.closed) {
changeStream = collection.watch(pipeline);
}
const stream2 = changeStream.stream(); Defensive patterns
Strategy: validation
Validate before calling
// Before calling stream()
if (changeStream.closed) {
// Recreate the change stream if needed
changeStream = collection.watch(pipeline, options);
}
const readable = changeStream.stream(); Try / catch
try {
const readable = changeStream.stream();
} catch (error) {
if (error instanceof MongoChangeStreamError && error.message === 'ChangeStream is closed') {
changeStream = collection.watch(pipeline, options);
readable = changeStream.stream();
}
} Prevention
- Always check changeStream.closed before calling stream()
- Do not reuse a closed ChangeStream instance; create a new one via watch()
- Track the lifecycle of your change streams explicitly in application code
When it happens
Trigger: Calling changeStream.stream() after changeStream.close() has been invoked, or after the cursor was closed due to an unrecoverable error or an invalidate event from the server.
Common situations: Code that re-obtains a stream after error handling closes the change stream; using for-await-of (which calls close() in its finally block) and then attempting stream(); the server sent an invalidate event that internally closed the cursor.
Related errors
- A change stream document has been received that lacks a…
- Cannot abort a stream that has already completed
- Cannot call abort() on a stream twice
- Cannot call abortTransaction after calling commitTransaction
- Cannot call abortTransaction twice
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/526748112b254bf1.
Report an issue: GitHub.
Appendix: source
Thrown at src/change_stream.ts:870
const cursor = this.cursor;
try {
await cursor.close();
} finally {
this._endStream();
}
}
/**
* Return a modified Readable stream including a possible transform method.
*
* NOTE: When using a Stream to process change stream events, the stream will
* NOT automatically resume in the case a resumable error is encountered.
*
* @throws MongoChangeStreamError if the underlying cursor or the change stream is closed
*/
stream(): Readable & AsyncIterable<TChange> {
if (this.closed) {
throw new MongoChangeStreamError(CHANGESTREAM_CLOSED_ERROR);
}
return this.cursor.stream();
}
/** @internal */
private _setIsEmitter(): void {
if (this.mode === 'iterator') {
// TODO(NODE-3485): Replace with MongoChangeStreamModeError
throw new MongoAPIError(
'ChangeStream cannot be used as an EventEmitter after being used as an iterator'
);
}
this.mode = 'emitter';
}
/** @internal */
private _setIsIterator(): void {View on GitHub (pinned to dce7939f86)