mongodb/node-mongodb-native · error · MongoServerClosedError
Server is closed
Error message
Server is closed
What it means
Thrown by Server.command() (src/sdam/server.ts:287) as MongoServerClosedError when an operation is attempted against a server whose internal state is STATE_CLOSING or STATE_CLOSED. The server (a single connection-pool owner within the topology) has been or is being torn down, so no command can be sent. Typically encountered after MongoClient.close() or during topology reconfiguration.
Source
Thrown at src/sdam/server.ts:287
this.emit('closed');
}
/**
* Immediately schedule monitoring of this server. If there already an attempt being made
* this will be a no-op.
*/
requestCheck(): void {
if (!this.loadBalanced) {
this.monitor?.requestCheck();
}
}
public async command<TResult>(
operation: AbstractOperation<TResult>,
timeoutContext: TimeoutContext
): Promise<InstanceType<typeof operation.SERVER_COMMAND_RESPONSE_TYPE>> {
if (this.s.state === STATE_CLOSING || this.s.state === STATE_CLOSED) {
throw new MongoServerClosedError();
}
const session = operation.session;
let conn = session?.pinnedConnection;
this.incrementOperationCount();
if (conn == null) {
try {
conn = await this.pool.checkOut({ timeoutContext, signal: operation.options.signal });
} catch (checkoutError) {
this.decrementOperationCount();
if (!(checkoutError instanceof PoolClearedError)) this.handleError(checkoutError);
throw checkoutError;
}
}
let reauthPromise: Promise<void> | null = null;
const cleanup = () => {View on GitHub (pinned to dce7939f86)
Solutions
- Ensure no in-flight operations when calling MongoClient.close(); await all promises first.
- Do not reuse a closed client — create a new MongoClient.
- Coordinate shutdown ordering: stop accepting new work, drain in-flight ops, then close.
- Catch MongoServerClosedError to avoid crashing during graceful shutdown.
Example fix
// before
await client.close();
await collection.findOne({}); // throws
// after
await collection.findOne({});
await client.close(); Defensive patterns
Strategy: try-catch
Validate before calling
let closed = false;
client.on('close', () => { closed = true; });
async function safeFind() {
if (closed) throw new Error('client is closed');
return collection.findOne({});
} Type guard
function isClientClosed(client): boolean {
return client.topology == null;
} Try / catch
try {
await collection.findOne({});
} catch (e) {
if (e instanceof MongoServerClosedError || /Server is closed/.test(e.message)) {
// skip or reconnect with a new client
}
throw e;
} Prevention
- Await all in-flight operations before calling client.close().
- Never reuse a closed MongoClient; construct a new one.
- Coordinate shutdown: stop new work, drain ops, then close.
- Track a 'closed' flag in application code alongside the client lifecycle.
When it happens
Trigger: Using a collection/db/client reference after client.close() resolved, issuing queries during shutdown, or holding a cursor/server reference that outlived the client. Also arises during failover when the targeted server is removed.
Common situations: Calling close() then reusing the client, shared singletons in long-running processes that get closed by a test teardown, or racing operations during application shutdown.
Related errors
- Client must be connected before running operations
- MongoClient must be connected to perform this operation
- illegal state transition from [${target.s.state}] => [${newS
- This batch has already been executed, create new batch to ex
- ChangeStream is closed
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/c73142e0663a308a.
Report an issue: GitHub.