{"record":{"id":"d162a71cdbdca0a1","repo":"brianc/node-postgres","slug":"sasl-scram-server-first-message-invalid-iteratio","errorCode":null,"errorMessage":"SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count","messagePattern":"SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/pg/lib/crypto/sasl.js","lineNumber":211,"sourceCode":"  const attrPairs = parseAttributePairs(data)\n\n  const nonce = attrPairs.get('r')\n  if (!nonce) {\n    throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing')\n  } else if (!isPrintableChars(nonce)) {\n    throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain printable characters')\n  }\n  const salt = attrPairs.get('s')\n  if (!salt) {\n    throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing')\n  } else if (!isBase64(salt)) {\n    throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt must be base64')\n  }\n  const iterationText = attrPairs.get('i')\n  if (!iterationText) {\n    throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing')\n  } else if (!/^[1-9][0-9]*$/.test(iterationText)) {\n    throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count')\n  }\n  const iteration = parseInt(iterationText, 10)\n\n  return {\n    nonce,\n    salt,\n    iteration,\n  }\n}\n\nfunction parseServerFinalMessage(serverData) {\n  const attrPairs = parseAttributePairs(serverData)\n  const error = attrPairs.get('e')\n  const serverSignature = attrPairs.get('v')\n\n  if (error) {\n    throw new Error(`SASL: SCRAM-SERVER-FINAL-MESSAGE: server returned error: \"${error}\"`)\n  }","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/brianc/node-postgres/blob/ff9d775abd12f29dd6df03945253b54eabbb29f2/packages/pg/lib/crypto/sasl.js#L193-L229","documentation":"Thrown by parseServerFirstMessage() when the iteration count (i= attribute) does not match the regex ^[1-9][0-9]*$ — i.e., it is not a string representation of a positive integer with no leading zeros. Per RFC 5802, the iteration count must be a positive integer. Values like 0, negative numbers, decimals, or non-numeric strings are rejected.","triggerScenarios":"At sasl.js:210-211, iterationText exists (the i= attribute is present) but does not match /^[1-9][0-9]*$/. Examples that trigger it: '0' (zero iterations), '-5' (negative), '1.5' (decimal), 'abc' (non-numeric), '01' (leading zero), '' (empty string after the equals sign would have been caught earlier by the truthiness check).","commonSituations":"A non-conformant or misconfigured server sending an unusual iteration count format; data corruption altering the numeric value; a server under attack sending crafted values to exhaust client resources (hence the scramMaxIterations cap check at lines 87-94).","solutions":["Verify the server is a standard PostgreSQL instance with correct SCRAM configuration.","Check for data corruption in the authentication stream.","Test the connection with psql to confirm the server sends a valid iteration count.","Ensure no proxy is altering the SASL message content."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await client.connect()\n} catch (err) {\n  if (err.message.includes('invalid iteration count')) {\n    throw new Error('SCRAM iteration count is malformed — verify server is standard PostgreSQL')\n  }\n  throw err\n}","preventionTips":["Verify the server is a standard PostgreSQL instance with correct SCRAM configuration.","Check for data corruption in the authentication stream.","Test with psql to confirm the server sends a valid iteration count.","Ensure no proxy alters the SASL message content."],"tags":["authentication","sasl","scram","protocol-error","connection"],"backgroundTag":null,"analyzedSha":"ff9d775abd12f29dd6df03945253b54eabbb29f2","analyzedAt":"2026-08-11T15:33:59.644Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}