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

  1. Ensure no in-flight operations when calling MongoClient.close(); await all promises first.
  2. Do not reuse a closed client — create a new MongoClient.
  3. Coordinate shutdown ordering: stop accepting new work, drain in-flight ops, then close.
  4. 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

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


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/c73142e0663a308a. Report an issue: GitHub.