brianc/node-postgres · error · Error
SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration count ${sv.itera
Error message
SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration count ${sv.iteration} exceeds scramMaxIterations of ${scramMaxIterations} What it means
Thrown during SCRAM session continuation (sasl.js:87-94) when the server's requested PBKDF2 iteration count exceeds the client's scramMaxIterations limit (default 100000, configurable via Client option scramMaxIterations; 0 disables the check). The iteration count determines how many PBKDF2 rounds are used to derive the salted key — an absurdly high value could be a denial-of-service vector (each authentication would take extremely long). The client refuses to honor iterations above the cap to bound CPU cost during login. This guard was added as a security hardening measure.
Source
Thrown at packages/pg/lib/crypto/sasl.js:88
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a non-empty string')
}
if (typeof serverData !== 'string') {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: serverData must be a string')
}
const sv = parseServerFirstMessage(serverData)
if (!sv.nonce.startsWith(session.clientNonce)) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce')
} else if (sv.nonce.length === session.clientNonce.length) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce is too short')
}
const scramMaxIterations =
typeof session.scramMaxIterations === 'number' ? session.scramMaxIterations : DEFAULT_MAX_SCRAM_ITERATIONS
// a value of 0 disables the iteration count check
if (scramMaxIterations !== 0 && sv.iteration > scramMaxIterations) {
throw new Error(
'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration count ' +
sv.iteration +
' exceeds scramMaxIterations of ' +
scramMaxIterations
)
}
const clientFirstMessageBare = 'n=*,r=' + session.clientNonce
const serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration
// without channel binding:
let channelBinding = stream ? 'eSws' : 'biws' // 'y,,' or 'n,,', base64-encoded
// override if channel binding is in use:
if (session.mechanism === 'SCRAM-SHA-256-PLUS') {
const peerCert = stream.getPeerCertificate().raw
let hashName = signatureAlgorithmHashFromCertificate(peerCert)
if (hashName === 'MD5' || hashName === 'SHA-1') hashName = 'SHA-256'View on GitHub (pinned to c5e8c9a57b)
Solutions
- Raise the client cap: new Client({ scramMaxIterations: 200000 }) to match the server's scram_iterations.
- Lower the server's scram_iterations to 100000 or below: ALTER SYSTEM SET scram_iterations = 100000.
- Set scramMaxIterations: 0 to disable the check entirely (not recommended — removes the DoS protection).
Example fix
// before
const client = new Client({ /* scramMaxIterations defaults to 100000 */ });
// server has scram_iterations=200000
// after
const client = new Client({ scramMaxIterations: 200000 }); Defensive patterns
Strategy: validation
Validate before calling
// Before constructing the client, check or align scramMaxIterations
const SERVER_SCRAM_ITERATIONS = 200000; // from your server config
const client = new Client({
scramMaxIterations: SERVER_SCRAM_ITERATIONS,
}); Try / catch
try {
await client.connect();
} catch (err) {
if (/iteration count.*exceeds scramMaxIterations/i.test(err.message)) {
// Extract the server's count from the message and raise the client cap
const match = err.message.match(/iteration count (\d+)/);
const serverIters = match ? parseInt(match[1], 10) : 200000;
client2 = new Client({ ...config, scramMaxIterations: serverIters });
await client2.connect();
} else {
throw err;
}
} Prevention
- Check the server's scram_iterations setting and set the client's scramMaxIterations to match or exceed it.
- Do not set scramMaxIterations to 0 unless you understand the DoS implications.
- Document the scram_iterations <-> scramMaxIterations relationship in your deployment config.
When it happens
Trigger: The server sends an i= value greater than the client's cap. With the default cap of 100000, a server configured with scram_iterations=200000 or higher would trigger it. Setting new Client({ scramMaxIterations: 10000 }) lowers the bar further.
Common situations: A PostgreSQL server (14+) with scram_iterations set very high for extra brute-force resistance. A misconfigured server sending a malformed iteration count. A development/test server with an artificially high value.
Related errors
- SASL: Only mechanism(s) ${candidates.join(' and ')} are supp
- SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not star
- SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce is too short
- SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not
- SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain pr
AI-assisted analysis of brianc/node-postgres@c5e8c9a57b (2026-08-03).
Data as JSON: /data/errors/3c20340712aaabfd.json.
Report an issue: GitHub.