{"id":"ad53972f11229f9e","repo":"mongodb/node-mongodb-native","slug":"unable-to-continue-scram-without-valid-nonce","errorCode":null,"errorMessage":"Unable to continue SCRAM without valid nonce","messagePattern":"Unable to continue SCRAM without valid nonce","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/cmap/auth/scram.ts","lineNumber":127,"sourceCode":"  const db = credentials.source;\n\n  const saslStartCmd = makeFirstMessage(cryptoMethod, credentials, nonce);\n  const response = await connection.command(ns(`${db}.$cmd`), saslStartCmd, undefined);\n  await continueScramConversation(cryptoMethod, response, authContext);\n}\n\nasync function continueScramConversation(\n  cryptoMethod: CryptoMethod,\n  response: Document,\n  authContext: AuthContext\n): Promise<void> {\n  const connection = authContext.connection;\n  const credentials = authContext.credentials;\n  if (!credentials) {\n    throw new MongoMissingCredentialsError('AuthContext must provide credentials.');\n  }\n  if (!authContext.nonce) {\n    throw new MongoInvalidArgumentError('Unable to continue SCRAM without valid nonce');\n  }\n  const nonce = authContext.nonce;\n\n  const db = credentials.source;\n  const username = cleanUsername(credentials.username);\n  const password = credentials.password;\n\n  const processedPassword =\n    cryptoMethod === 'sha256' ? saslprep(password) : passwordDigest(username, password);\n\n  const payload: Binary = ByteUtils.isUint8Array(response.payload)\n    ? new Binary(response.payload)\n    : response.payload;\n\n  const dict = parsePayload(payload);\n\n  const iterations = parseInt(dict.i, 10);\n  if (iterations && iterations < 4096) {","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/cmap/auth/scram.ts#L109-L145","documentation":"Thrown by continueScramConversation() (scram.ts:127) as a MongoInvalidArgumentError when authContext.nonce is falsy at the point of computing the client proof. Like error 82, this indicates the SCRAM conversation continued without prepare() having generated and stored a nonce. An internal invariant violation, not normally user-reachable.","triggerScenarios":"continueScramConversation invoked without a preceding successful prepare(); a driver-internal state corruption where the nonce was cleared between prepare and continue; reauthenticating a pooled connection whose AuthContext was reset improperly.","commonSituations":"Driver defect; non-standard subclassing of ScramSHA that overrides prepare() without setting the nonce; concurrent reuse of an AuthContext across two auth attempts.","solutions":["Ensure prepare() runs to completion before auth()/continueScramConversation()","Do not share a single AuthContext across concurrent connections","Report as a bug with the driver version if using an unmodified MongoClient"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await client.connect();\n} catch (e) {\n  if (e instanceof MongoInvalidArgumentError && /nonce/.test(e.message)) {\n    // internal invariant - file a driver bug\n  }\n  throw e;\n}","preventionTips":["Do not override prepare() in ScramSHA subclasses without calling super","Never reuse a single AuthContext across two concurrent auth attempts","Pin driver versions in CI to detect regressions"],"tags":["auth","scram","nonce","internal-state"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}