mongodb/node-mongodb-native · error · MongoRuntimeError

Server returned an invalid iteration count

Error message

Server returned an invalid iteration count ${iterations}

What it means

Thrown by continueScramConversation (scram.ts:147) when the server's SASL response reports an iteration count less than 4096. RFC 5802 mandates a minimum of 4096 PBKDF2 iterations for SCRAM-SHA-256; a lower value is either a non-compliant server or a sign of a tampered/downgrade attempt. Raised as MongoRuntimeError.

Solutions

  1. Upgrade or reconfigure the MongoDB server to advertise at least 4096 iterations
  2. Remove any intermediary proxy/gateway that may rewrite SASL payloads
  3. If using SCRAM-SHA-256, confirm the server supports the modern defaults
  4. Treat this as a potential security incident and verify the connection is not being downgraded
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await client.connect();
} catch (err) {
  if (err instanceof MongoRuntimeError && /invalid iteration count/.test(err.message)) {
    // server is non-compliant or downgrade attack; do NOT retry against same endpoint
    alertSecurityTeam(err);
  }
  throw err;
}

Prevention

When it happens

Trigger: The server's saslStart response payload contains an 'i' field (iteration count) that parses to a number greater than 0 but below 4096. The check skips when iterations is falsy/0 (legacy), so only an explicit low positive value triggers it.

Common situations: A misconfigured or very old MongoDB-compatible server advertising <4096 iterations. A man-in-the-middle tampering with the SASL payload to weaken key derivation. A non-conformant proxy/gateway rewriting the response.

Related errors


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

Appendix: source

Thrown at src/cmap/auth/scram.ts:147

  const nonce = authContext.nonce;

  const db = credentials.source;
  const username = cleanUsername(credentials.username);
  const password = credentials.password;

  const processedPassword =
    cryptoMethod === 'sha256' ? saslprep(password) : passwordDigest(username, password);

  const payload: Binary = ByteUtils.isUint8Array(response.payload)
    ? new Binary(response.payload)
    : response.payload;

  const dict = parsePayload(payload);

  const iterations = parseInt(dict.i, 10);
  if (iterations && iterations < 4096) {
    // TODO(NODE-3483)
    throw new MongoRuntimeError(`Server returned an invalid iteration count ${iterations}`);
  }

  const salt = dict.s;
  const rnonce = dict.r;
  if (rnonce.startsWith('nonce')) {
    // TODO(NODE-3483)
    throw new MongoRuntimeError(`Server returned an invalid nonce: ${rnonce}`);
  }

  // Set up start of proof
  const withoutProof = `c=biws,r=${rnonce}`;
  const saltedPassword = await HI(
    processedPassword,
    ByteUtils.fromBase64(salt),
    iterations,
    cryptoMethod
  );

View on GitHub (pinned to dce7939f86)