mongodb/node-mongodb-native · error · MongoOperationTimeoutError

Timed out during server selection

Error message

Timed out during server selection

What it means

Thrown by the server-selection loop in Topology.selectServer when CSOT (Client-Side Operation Timeout) is enabled and no server matching the read preference becomes available before the timeout expires. It is a MongoOperationTimeoutError whose `cause` is a MongoServerSelectionError, so it surfaces the underlying selection failure while respecting the CSOT contract. Without CSOT the driver instead throws the bare MongoServerSelectionError.

Solutions

  1. Verify the cluster is reachable from the host: connect with `mongosh` using the same URI, or run `nc -vz <host> <port>`.
  2. Increase `timeoutMS` for the operation, or remove it so the default `serverSelectionTimeoutMS` (usually 30s) applies.
  3. Check the read preference: a `secondaryPreferred`/`nearest` call against a single-node standalone will never match; use `primary`.
  4. Inspect driver SDAM logs (set `mongodb:DEBUG`) to see the server descriptions and errors reported by heartbeats.
  5. Confirm TLS/auth credentials in the URI match the server, since failed handshakes leave the server Unknown and unselectable.

Example fix

// before
await client.db('app').collection('c').findOne({}, { timeoutMS: 200 });

// after: give selection a realistic window, or fall back to the default
await client.db('app').collection('c').findOne({}, { timeoutMS: 5000 });
Defensive patterns

Strategy: try-catch

Validate before calling

// Before opening the client, sanity-check reachability of the first seed.
import { MongoClient } from 'mongodb';

async function reachable(uri, ms = 2000) {
  const c = new MongoClient(uri, { serverSelectionTimeoutMS: ms });
  try {
    await c.db('admin').command({ ping: 1 });
    return true;
  } catch {
    return false;
  } finally {
    await c.close();
  }
}

if (!(await reachable(uri))) throw new Error('cluster unreachable');

Try / catch

try {
  await collection.findOne({}, { timeoutMS });
} catch (err) {
  if (err.name === 'MongoOperationTimeoutError' || err.name === 'MongoServerSelectionError') {
    // log SDAM state, alert, fall back, or rethrow with context
    logger.error('cannot reach a suitable server', { cause: err.cause });
    throw err;
  }
  throw err;
}

Prevention

When it happens

Trigger: Any operation run on a MongoClient where `timeoutMS` (per-call or client-wide) is set and `selectServer` cannot find a usable server within that window: e.g. `collection.findOne({}, { timeoutMS: 500 })` while the cluster is unreachable, or a `withTransaction(..., { timeoutMS: 1000 })` whose first operation cannot pin a server.

Common situations: Network partition or firewall blocking the MongoDB port; replica set down or in the middle of an election with no primary for the read preference; wrong host/port in the connection string; TLS handshake failing; the `serverSelectionTimeoutMS` being overridden by a small `timeoutMS`. Common when migrating to per-operation timeouts (CSOT) introduced in driver v6.

Understand the failure class

Related errors


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

Appendix: source

Thrown at src/sdam/topology.ts:660

        if (
          this.client.mongoLogger?.willLog(
            MongoLoggableComponent.SERVER_SELECTION,
            SeverityLevel.DEBUG
          )
        ) {
          this.client.mongoLogger?.debug(
            MongoLoggableComponent.SERVER_SELECTION,
            new ServerSelectionFailedEvent(
              selector,
              this.description,
              timeoutError,
              options.operationName
            )
          );
        }

        if (options.timeoutContext?.csotEnabled()) {
          throw new MongoOperationTimeoutError('Timed out during server selection', {
            cause: timeoutError
          });
        }
        throw timeoutError;
      }
      // Other server selection error
      throw error;
    } finally {
      abortListener?.[kDispose]();
      if (!options.timeoutContext || options.timeoutContext.clearServerSelectionTimeout) {
        timeout?.clear();
      }
    }
  }
  /**
   * Update the internal TopologyDescription with a ServerDescription
   *
   * @param serverDescription - The server to update in the internal list of server descriptions

View on GitHub (pinned to dce7939f86)