brianc/node-postgres · error · Error
SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain…
Error message
SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain printable characters
What it means
Thrown by parseServerFirstMessage() when the server's nonce contains characters outside the printable ASCII range defined by isPrintableChars() — specifically bytes 0x21-0x2B and 0x2D-0x7E (printable ASCII excluding comma). Per RFC 5802 the nonce must be printable. Non-printable characters could break the protocol's comma-delimited structure or indicate data corruption.
Solutions
- Verify network integrity between client and server — check for corrupting proxies, firewalls, or VPNs.
- Confirm the server is a legitimate PostgreSQL instance and not a spoofed/malicious endpoint.
- Enable SSL/TLS to protect the authentication stream from in-transit corruption.
- Test the connection with psql from the same host to isolate the issue.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await client.connect()
} catch (err) {
if (err.message.includes('nonce must only contain printable characters')) {
throw new Error('Data corruption in SASL nonce — check network integrity and SSL configuration')
}
throw err
} Prevention
- Enable SSL/TLS to protect the authentication stream from in-transit corruption.
- Verify no proxy or firewall is altering authentication data.
- Confirm the server is a legitimate PostgreSQL instance.
- Test the connection from the same host using psql.
When it happens
Trigger: At sasl.js:198-199, isPrintableChars(nonce) returns false. The nonce value extracted from the r= attribute contains at least one character with a char code outside 0x21-0x2B or 0x2D-0x7E — e.g., a control character (0x00-0x1F), DEL (0x7F), a comma (0x2C), or a high byte (0x80+).
Common situations: Data corruption in transit introducing binary/noise bytes into the nonce field; a buggy or malicious server injecting crafted nonce values; an encoding mismatch where raw binary data leaks into a text field; a proxy that re-encodes or mangles the authentication stream.
Related errors
- SASL: Invalid attribute pair entry
- SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is…
- SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature must be…
- SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count
- SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing
AI-assisted analysis of brianc/node-postgres@ff9d775abd (2026-08-11).
Data as JSON: /api/errors/9db1fd5f95821ac9.
Report an issue: GitHub.
Appendix: 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 ff9d775abd)