mongodb/node-mongodb-native · error · MongoInvalidArgumentError
Option "maxStalenessSeconds" must be at least
Error message
Option "maxStalenessSeconds" must be at least ${maxStalenessVariance} seconds What it means
Thrown by maxStalenessReducer() (src/sdam/server_selection.ts:132) as MongoInvalidArgumentError when maxStalenessSeconds is below the dynamic staleness variance floor, computed as (heartbeatFrequencyMS + IDLE_WRITE_PERIOD) / 1000. This floor accounts for clock skew and heartbeat latency per the max-staleness spec. The threshold varies with the topology's heartbeat frequency.
Solutions
- Increase maxStalenessSeconds to at least the value in the error message (the computed variance floor).
- Use the absolute minimum of 90 seconds (see error 336) as a safe default.
- If heartbeatFrequencyMS is high, lower it to reduce the variance floor.
Example fix
// before
new ReadPreference('secondary', undefined, { maxStalenessSeconds: 30 });
// after
new ReadPreference('secondary', undefined, { maxStalenessSeconds: 90 }); Defensive patterns
Strategy: validation
Validate before calling
const IDLE_WRITE_PERIOD = 10;
function safeMaxStaleness(v, heartbeatFrequencyMS = 10000) {
const variance = (heartbeatFrequencyMS / 1000) + IDLE_WRITE_PERIOD;
if (v < variance) throw new Error(`maxStalenessSeconds must be >= ${variance}`);
return v;
} Type guard
function isAboveVariance(v, heartbeatFrequencyMS = 10000): v is number {
return typeof v === 'number' && v >= ((heartbeatFrequencyMS / 1000) + 10);
} Try / catch
try {
await collection.findOne({}, { readPreference: new ReadPreference('secondary', undefined, { maxStalenessSeconds }) });
} catch (e) {
if (e instanceof MongoInvalidArgumentError && /maxStalenessSeconds/.test(e.message)) {
// bump staleness and retry
}
throw e;
} Prevention
- Use at least 90 seconds for maxStalenessSeconds to satisfy both the variance and absolute floors.
- Account for heartbeatFrequencyMS when tuning the value.
- Document the spec-derived floors for your team.
When it happens
Trigger: Setting maxStalenessSeconds to a small value (e.g. 10-30s) that is below the per-topology variance floor (~heartbeatFrequencyMS/1000 + 10s).
Common situations: Aggressive latency requirements leading developers to set very small staleness windows without accounting for heartbeat overhead.
Related errors
- Option "maxStalenessSeconds" must be at least
- Invalid read preference specified
- maxStalenessSeconds must be a positive integer
- Primary read preference cannot be combined with…
- Invalid read preference mode
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/88b48331da9ca49e.
Report an issue: GitHub.
Appendix: source
Thrown at src/sdam/server_selection.ts:132
* @param readPreference - The read preference providing max staleness guidance
* @param topologyDescription - The topology description
* @param servers - The list of server descriptions to be reduced
* @returns The list of servers that satisfy the requirements of max staleness
*/
function maxStalenessReducer(
readPreference: ReadPreference,
topologyDescription: TopologyDescription,
servers: ServerDescription[]
): ServerDescription[] {
if (readPreference.maxStalenessSeconds == null || readPreference.maxStalenessSeconds < 0) {
return servers;
}
const maxStaleness = readPreference.maxStalenessSeconds;
const maxStalenessVariance =
(topologyDescription.heartbeatFrequencyMS + IDLE_WRITE_PERIOD) / 1000;
if (maxStaleness < maxStalenessVariance) {
throw new MongoInvalidArgumentError(
`Option "maxStalenessSeconds" must be at least ${maxStalenessVariance} seconds`
);
}
if (maxStaleness < SMALLEST_MAX_STALENESS_SECONDS) {
throw new MongoInvalidArgumentError(
`Option "maxStalenessSeconds" must be at least ${SMALLEST_MAX_STALENESS_SECONDS} seconds`
);
}
if (topologyDescription.type === TopologyType.ReplicaSetWithPrimary) {
const primary: ServerDescription = Array.from(topologyDescription.servers.values()).filter(
primaryFilter
)[0];
return servers.filter((server: ServerDescription) => {
const stalenessMS =
server.lastUpdateTime -View on GitHub (pinned to dce7939f86)