MongoOperationTimeoutError: Operation timed out is raised when the driver waits longer than the configured server selection, socket, or operation timeout for a Node to respond. It usually means a slow query, a disconnected replica, or a network boundary closing the TCP connection before the request completes.
The MongoDB driver throws MongoOperationTimeoutError whenever it gives up on an operation that has already started but exceeded one of its timeout budgets. The Node.js driver builds on several timeouts: 1. `serverSelectionTimeoutMS` controls how long the driver blocks while hunting for an eligible server before the operation even starts. 2. `socketTimeoutMS` caps how long the driver will wait for data once it has a connected socket. 3. `maxTimeMS` (per operation) requests the server abort the work if it exceeds that duration. When a server is slow, unavailable, or drops the socket, the driver hits one of these deadlines and surfaces “Operation timed out,” meaning the TCP connection was alive but the query/command never returned in time. The error differs from a connection error because it typically follows a successful handshake rather than a refusal.
Extend the driver’s timeout windows so it can wait longer for a primary, especially in multi-region or heavy-traffic clusters:
const client = new MongoClient(uri, {
serverSelectionTimeoutMS: 60000, // wait up to 60s for a healthy node
socketTimeoutMS: 45000, // wait 45s for a response once connected
connectTimeoutMS: 30000,
waitQueueTimeoutMS: 20000,
});The MongoDB docs recommend tuning these [connection options](https://www.mongodb.com/docs/drivers/node/current/connect/connection-options/#std-label-node-connection-options) based on your expected latency. Driver defaults are safe for local clusters, but distributed deployments often need the extra headroom.
Apply maxTimeMS to operations that scan large collections so the server kills them before the driver’s deadline. Also ensure indexes cover the query and limit the result set:
const cursor = collection.find({ status: 'active' });
cursor.maxTimeMS(10000); // let MongoDB abort after 10 seconds
await cursor.toArray();Add indexes on the filters and projections you use, and paginate rather than requesting the entire dataset. maxTimeMS appears in the [how to limit server execution time guide](https://www.mongodb.com/docs/drivers/node/current/fundamentals/connection/#how-to-limit-server-execution-time) and protects both the client and the server from runaway operations.
Use the shell and monitoring tools to ensure replica set members are reachable, not lagging, and have the resources to finish operations:
mongosh --quiet <<'EOF'
printjson(rs.status());
printjson(db.serverStatus().connections);
printjson(db.currentOp({secs_running: {$gt: 10}}));
EOFWatch mongostat or Atlas metrics for high latency, CPU spikes, or election storms. If the driver cannot find a PRIMARY before serverSelectionTimeoutMS, it will return the same timeout error even if the network is fine.
Load balancers, proxy servers, and corporate firewalls often kill idle connections in 30–60 seconds. Match those values to your driver settings and enable TCP keepalive:
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;On AWS ALB/ELB, bump the Idle Timeout to 120s or more. Azure and GCP have similar settings. Ensure keepAlive packets actually flow (the Node driver enables keepalive by default). Without this, the driver may time out even though the server would eventually respond.
Wrap operations in retries when they are idempotent. The driver already supports retryReads and retryWrites, but application-level retries let you handle non-idempotent work safely:
const result = await retry(async () => {
return await collection.updateOne({ _id }, { $inc: { counter: 1 } });
}, {
retries: 3,
minTimeout: 1000,
maxTimeout: 10000,
});Use a library like p-retry (npm) and log the retry attempts. If retries still get timeouts, a deeper bottleneck or timeout configuration must be addressed before adding more attempts.
The driver performs heartbeat checks every heartbeatFrequencyMS milliseconds to keep track of replica set members. If heartbeats fail, the driver spends the serverSelectionTimeoutMS budget trying to find another node. Setting this value too low in cross-region setups often looks like "Operation timed out" because the driver never finishes selecting.
Similarly, the server honors maxTimeMS and will throw its own timeout before returning results. While the default socketTimeoutMS is 0 (no limit), intermediate proxies usually impose their own limit, so matching those values prevents silent drops.
Monitor currentOp() and Atlas Alerts for operation durations, and consider increasing maxPoolSize/waitQueueTimeoutMS if you see pool exhaustion symptoms alongside the timeouts.
StaleShardVersion: shard version mismatch
How to fix "StaleShardVersion: shard version mismatch" in MongoDB
MongoServerError: PlanExecutor error during aggregation :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation.
How to fix "QueryExceededMemoryLimitNoDiskUseAllowed" in MongoDB
MissingSchemaError: Schema hasn't been registered for model
How to fix "MissingSchemaError: Schema hasn't been registered for model" in MongoDB/Mongoose
CastError: Cast to ObjectId failed for value "abc123" at path "_id"
How to fix "CastError: Cast to ObjectId failed" in MongoDB
OverwriteModelError: Cannot overwrite model once compiled
How to fix "OverwriteModelError: Cannot overwrite model once compiled" in MongoDB