brianc/node-postgres · error · Error
SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain pr
Error message
SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain printable characters
What it means
Thrown by parseServerFirstMessage (sasl.js:198-199) when the server's nonce (r= value) contains characters outside the printable ASCII range defined by RFC 5802 (%x21-2B / %x2D-7E, excluding comma). The isPrintableChars function validates each byte; non-printable or non-ASCII bytes in the nonce could indicate corruption or a deliberately crafted malicious response. This is a protocol-conformance and safety guard.
Source
Thrown at packages/pg/lib/crypto/sasl.js:199
text.split(',').map((attrValue) => {
if (!/^.=/.test(attrValue)) {
throw new Error('SASL: Invalid attribute pair entry')
}
const name = attrValue[0]
const value = attrValue.substring(2)
return [name, value]
})
)
}
function parseServerFirstMessage(data) {
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,View on GitHub (pinned to c5e8c9a57b)
Solutions
- Ensure a clean, unproxied connection to the PostgreSQL server.
- Enable SSL to protect the authentication exchange from corruption or injection.
- If using a custom PostgreSQL-compatible server, verify its SCRAM nonce generation uses only printable ASCII.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await client.connect();
} catch (err) {
if (/nonce must only contain printable characters/i.test(err.message)) {
console.error('SCRAM nonce contains non-printable bytes — corruption or malicious server.');
}
throw err;
} Prevention
- Use SSL/TLS to protect the SCRAM exchange from corruption or injection.
- Verify the server's SCRAM nonce generation produces printable ASCII only.
- Investigate network infrastructure for data integrity issues if this recurs.
When it happens
Trigger: The server's r= attribute contains control characters, high-byte (>0x7E) characters, spaces, or commas. The isPrintableChars check at sasl.js:150-158 examines every character code.
Common situations: Wire-level data corruption introducing non-printable bytes. A malicious or buggy server injecting invalid nonce characters. Extremely rare with compliant PostgreSQL servers.
Related errors
- SASL: Invalid attribute pair entry
- SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing
- SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing
- SASL: Only mechanism(s) ${candidates.join(' and ')} are supp
- SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a
AI-assisted analysis of brianc/node-postgres@c5e8c9a57b (2026-08-03).
Data as JSON: /data/errors/9db1fd5f95821ac9.json.
Report an issue: GitHub.