mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Unable to continue SCRAM without valid nonce

Error message

Unable to continue SCRAM without valid nonce

What it means

Thrown by continueScramConversation (scram.ts:127) when authContext.nonce is unset while attempting the second SASL round. The nonce is generated in prepare() and must persist on the context for the proof computation; reaching this throw indicates the context lost its nonce or auth ran without prepare. Raised as MongoInvalidArgumentError.

Solutions

  1. Report a driver bug if reached via the public API with reproduction steps
  2. If using the internal API, ensure prepare() runs first so authContext.nonce is set
  3. Upgrade the driver to pick up any nonce-retention fix
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await client.connect();
} catch (err) {
  if (err instanceof MongoInvalidArgumentError && /nonce/.test(err.message)) {
    // internal invariant on the conversation path; report with topology/repro details
    reportDriverBug(err);
  }
  throw err;
}

Prevention

When it happens

Trigger: Entering continueScramConversation (via speculative response handling or executeScram) when authContext.nonce was never set or was cleared. Mirrors the executeScram nonce invariant (scram.ts:106) but on the conversation-continuation path.

Common situations: A driver regression where the nonce is not retained across the speculative-to-continue transition. Forked auth providers that reset the context. Re-authentication after pool reset.

Related errors


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

Appendix: source

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

  const db = credentials.source;

  const saslStartCmd = makeFirstMessage(cryptoMethod, credentials, nonce);
  const response = await connection.command(ns(`${db}.$cmd`), saslStartCmd, undefined);
  await continueScramConversation(cryptoMethod, response, authContext);
}

async function continueScramConversation(
  cryptoMethod: CryptoMethod,
  response: Document,
  authContext: AuthContext
): Promise<void> {
  const connection = authContext.connection;
  const credentials = authContext.credentials;
  if (!credentials) {
    throw new MongoMissingCredentialsError('AuthContext must provide credentials.');
  }
  if (!authContext.nonce) {
    throw new MongoInvalidArgumentError('Unable to continue SCRAM without valid nonce');
  }
  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) {

View on GitHub (pinned to dce7939f86)