mongodb/node-mongodb-native · error · MongoTailableCursorError
Tailable cursor does not support batchSize
Error message
Tailable cursor does not support batchSize
What it means
Thrown as a MongoTailableCursorError (a subclass of MongoAPIError) from batchSize() when cursorOptions.tailable is true. A tailable cursor follows the tail of a capped collection and must not pin itself to a fixed batch size, because doing so would interfere with the await/blocking semantics that let tailing work; the driver rejects batchSize on tailable cursors to prevent this. The guard runs before the integer check, and only when the cursor is not yet initialized.
Solutions
- Remove the batchSize call/option for tailable cursors; rely on the server default batch sizing.
- If you need backpressure control on a tailable cursor, manage it at the consumer side (e.g. stream highWaterMark) rather than via batchSize.
- Split your cursor-builder so tailable and non-tailable paths do not share the batchSize configuration.
Example fix
// before: batchSize on a tailable cursor
const cursor = collection.find(filter, { tailable: true, awaitData: true });
cursor.batchSize(100); // throws MongoTailableCursorError
// after: drop batchSize for tailable cursors
const cursor = collection.find(filter, { tailable: true, awaitData: true }); Defensive patterns
Strategy: validation
Validate before calling
if (opts.tailable && opts.batchSize != null) {
throw new RangeError('batchSize is not supported on tailable cursors');
} Prevention
- Do not set batchSize on tailable cursors.
- Split cursor-builder helpers into tailable and non-tailable variants.
- Control backpressure at the consumer/stream level for tailable cursors.
When it happens
Trigger: Building a cursor with addCursorFlag('tailable', true) (or { tailable: true }) and then calling cursor.batchSize(N); configuring a tailable change-stream-style cursor and trying to tune batch size.
Common situations: Reusing a generic cursor-builder helper that always sets batchSize, on a tailable cursor; enabling tailable after setting batchSize in a chained config.
Related errors
- Cannot set tailable cursor's timeoutMode to LIFETIME
- Cannot specify maxAwaitTimeMS >= timeoutMS for a tailable…
- Operation "batchSize" requires an integer
- Argument for maxTimeMS must be a number
- Argument "iterator" must be a function
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/62767a4690e0d0ba.
Report an issue: GitHub.
Appendix: source
Thrown at src/cursor/abstract_cursor.ts:804
maxTimeMS(value: number): this {
this.throwIfInitialized();
if (typeof value !== 'number') {
throw new MongoInvalidArgumentError('Argument for maxTimeMS must be a number');
}
this.cursorOptions.maxTimeMS = value;
return this;
}
/**
* Set the batch size for the cursor.
*
* @param value - The number of documents to return per batch. See {@link https://www.mongodb.com/docs/manual/reference/command/find/|find command documentation}.
*/
batchSize(value: number): this {
this.throwIfInitialized();
if (this.cursorOptions.tailable) {
throw new MongoTailableCursorError('Tailable cursor does not support batchSize');
}
if (typeof value !== 'number') {
throw new MongoInvalidArgumentError('Operation "batchSize" requires an integer');
}
this.cursorOptions.batchSize = value;
return this;
}
/**
* Rewind this cursor to its uninitialized state. Any options that are present on the cursor will
* remain in effect. Iterating this cursor will cause new queries to be sent to the server, even
* if the resultant data has already been retrieved by this cursor.
*/
rewind(): void {
if (this.timeoutContext && this.timeoutContext.owner !== this) {
throw new MongoAPIError(`Cannot rewind cursor that does not own its timeout context.`);View on GitHub (pinned to dce7939f86)