brianc/node-postgres · error · Error
SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count
Error message
SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count
What it means
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.
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.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await client.connect()
} catch (err) {
if (err.message.includes('invalid iteration count')) {
throw new Error('SCRAM iteration count is malformed — verify server is standard PostgreSQL')
}
throw err
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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).
Related errors
- SASL: Invalid attribute pair entry
- SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is…
- SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing
- SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing
- SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain…
AI-assisted analysis of brianc/node-postgres@ff9d775abd (2026-08-11).
Data as JSON: /api/errors/d162a71cdbdca0a1.
Report an issue: GitHub.
Appendix: source
Thrown at packages/pg/lib/crypto/sasl.js:211
const attrPairs = parseAttributePairs(data)
const nonce = attrPairs.get('r')
if (!nonce) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing')
} else if (!isPrintableChars(nonce)) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain printable characters')
}
const salt = attrPairs.get('s')
if (!salt) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing')
} else if (!isBase64(salt)) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt must be base64')
}
const iterationText = attrPairs.get('i')
if (!iterationText) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing')
} else if (!/^[1-9][0-9]*$/.test(iterationText)) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count')
}
const iteration = parseInt(iterationText, 10)
return {
nonce,
salt,
iteration,
}
}
function parseServerFinalMessage(serverData) {
const attrPairs = parseAttributePairs(serverData)
const error = attrPairs.get('e')
const serverSignature = attrPairs.get('v')
if (error) {
throw new Error(`SASL: SCRAM-SERVER-FINAL-MESSAGE: server returned error: "${error}"`)
}View on GitHub (pinned to ff9d775abd)