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

  1. Confirm you are connecting to a real PostgreSQL server (not a mock or incompatible proxy that speaks a different protocol).
  2. Remove any intermediary proxies, load balancers, or SSL terminators between the client and PostgreSQL that might corrupt the auth stream.
  3. Use psql or another client to verify the same connection string authenticates successfully.
  4. 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

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


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)