brianc/node-postgres · error · Error
SASL: Invalid attribute pair entry
Error message
SASL: Invalid attribute pair entry
What it means
Thrown inside parseAttributePairs() when a comma-separated segment of a SASL message does not match the pattern ^.= (a single character followed by an equals sign). Every SASL attribute pair must follow the form <type-char>=<value>. A segment failing this check means the server sent a structurally malformed SASL message.
Solutions
- Confirm you are connecting to a real PostgreSQL server (not a mock or incompatible proxy that speaks a different protocol).
- Remove any intermediary proxies, load balancers, or SSL terminators between the client and PostgreSQL that might corrupt the auth stream.
- Use psql or another client to verify the same connection string authenticates successfully.
- Update node-postgres to the latest version for any protocol-handling fixes.
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify you're talking to a real PostgreSQL server:
const net = require('net')
const sock = net.connect(port, host)
sock.on('connect', () => { sock.end(); console.log('Port reachable') })
sock.on('error', (e) => console.error('Cannot reach server:', e.message)) Try / catch
try {
await client.connect()
} catch (err) {
if (err.message.includes('Invalid attribute pair entry')) {
throw new Error('Malformed SASL message from server — verify target is PostgreSQL and no proxy is corrupting traffic')
}
throw err
} Prevention
- Confirm the server is a real PostgreSQL instance, not a protocol-incompatible proxy or mock.
- Remove intermediaries (load balancers, custom proxies) that may corrupt the SASL message format.
- Enable SSL/TLS to protect authentication data integrity.
- Test the connection with psql to establish a baseline.
When it happens
Trigger: text.split(',').map() iterates over each comma-delimited segment. If any segment does not match /^.=/ — for example an empty string (from leading comma, trailing comma, or double comma), a segment missing the equals sign, or a multi-character attribute name — the error fires at sasl.js:182-183.
Common situations: Connecting to a non-PostgreSQL server that responds with a non-conformant SASL message; a proxy or connection pooler corrupting the authentication stream by inserting or dropping bytes; network-level data corruption; an intentionally malicious server sending crafted malformed messages.
Related errors
- SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is…
- SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count
- 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/78ce6505edf9fd53.
Report an issue: GitHub.
Appendix: source
Thrown at packages/pg/lib/crypto/sasl.js:183
* base64-3 = 3base64-char "="
*
* base64-2 = 2base64-char "=="
*
* base64 = *base64-4 [base64-3 / base64-2]
*/
function isBase64(text) {
return /^(?:[a-zA-Z0-9+/]{4})*(?:[a-zA-Z0-9+/]{2}==|[a-zA-Z0-9+/]{3}=)?$/.test(text)
}
function parseAttributePairs(text) {
if (typeof text !== 'string') {
throw new TypeError('SASL: attribute pairs text must be a string')
}
return new Map(
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')View on GitHub (pinned to ff9d775abd)