brianc/node-postgres · error · Error
SASL: Only mechanism(s) ${candidates.join(' and ')} are supp
Error message
SASL: Only mechanism(s) ${candidates.join(' and ')} are supported What it means
Thrown during SCRAM authentication (sasl.js:41-43) when the PostgreSQL server's advertised SASL mechanism list does not include SCRAM-SHA-256 or SCRAM-SHA-256-PLUS. node-postgres only implements the SCRAM-SHA-256 family per RFC 5802/7677; older authentication methods (like SCRAM-SHA-512 or GSSAPI) are not supported. The candidates array is built dynamically: SCRAM-SHA-256-PLUS is added first if a TLS stream with channel-binding support is available, then SCRAM-SHA-256. If the server offers neither, authentication cannot proceed.
Source
Thrown at packages/pg/lib/crypto/sasl.js:42
// RFC 3454 Table B.1 — "commonly mapped to nothing". The set intentionally
// contains zero-width joiners and variation selectors — the very characters
// ESLint's no-misleading-character-class warns about — because they combine
// with their neighbors and the RFC strips them for that reason.
// eslint-disable-next-line no-misleading-character-class
const mappedToNothing = /[\u00AD\u034F\u1806\u180B\u180C\u180D\u200C\u200D\u2060\uFE00-\uFE0F\uFEFF]/g
return password.replace(nonAsciiSpace, ' ').replace(mappedToNothing, '').normalize('NFKC')
}
const DEFAULT_MAX_SCRAM_ITERATIONS = 100000
function startSession(mechanisms, stream, scramMaxIterations = DEFAULT_MAX_SCRAM_ITERATIONS) {
const candidates = ['SCRAM-SHA-256']
if (stream) candidates.unshift('SCRAM-SHA-256-PLUS') // higher-priority, so placed first
const mechanism = candidates.find((candidate) => mechanisms.includes(candidate))
if (!mechanism) {
throw new Error('SASL: Only mechanism(s) ' + candidates.join(' and ') + ' are supported')
}
if (mechanism === 'SCRAM-SHA-256-PLUS' && typeof stream.getPeerCertificate !== 'function') {
// this should never happen if we are really talking to a Postgres server
throw new Error('SASL: Mechanism SCRAM-SHA-256-PLUS requires a certificate')
}
const clientNonce = crypto.randomBytes(18).toString('base64')
const gs2Header = mechanism === 'SCRAM-SHA-256-PLUS' ? 'p=tls-server-end-point' : stream ? 'y' : 'n'
return {
mechanism,
clientNonce,
response: gs2Header + ',,n=*,r=' + clientNonce,
message: 'SASLInitialResponse',
scramMaxIterations,
}
}View on GitHub (pinned to c5e8c9a57b)
Solutions
- Ensure the PostgreSQL server supports SCRAM-SHA-256 by setting password_encryption='scram-sha-256' in postgresql.conf and re-setting the user's password.
- If connecting through PgBouncer, verify its auth configuration passes through SCRAM-SHA-256.
- Upgrade node-postgres to the latest version; if your server only offers scram-sha-512, you may need a driver or server-side change to enable scram-sha-256.
Example fix
-- on the PostgreSQL server ALTER SYSTEM SET password_encryption = 'scram-sha-256'; SELECT pg_reload_conf(); ALTER ROLE myuser WITH PASSWORD 'mypass'; -- re-hash with new scheme
Defensive patterns
Strategy: try-catch
Try / catch
try {
await client.connect();
} catch (err) {
if (/Only mechanism.*SCRAM-SHA-256/i.test(err.message)) {
console.error('Server does not offer SCRAM-SHA-256. Check password_encryption on the server.');
}
throw err;
} Prevention
- Ensure the PostgreSQL server has password_encryption='scram-sha-256' and roles are re-hashed.
- If using PgBouncer, verify it is configured to pass SCRAM auth through (auth_type).
- Keep node-postgres updated; newer versions may add support for additional SASL mechanisms.
When it happens
Trigger: Connecting to a PostgreSQL server configured with password_encryption=scram-sha-512-only or an older server (pre-10) that only offers MD5 or cleartext, but where the auth flow reaches the SASL handler. Also if a proxy or connection pooler (like PgBouncer in certain modes) strips or rewrites the mechanism list.
Common situations: PostgreSQL 18+ defaults to scram-sha-512; if the server is configured to only accept that, this client cannot authenticate. A misconfigured PgBouncer or a man-in-the-middle altering the auth negotiation. Connecting to a non-PostgreSQL server that speaks a different SASL dialect.
Related errors
- SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not star
- SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce is too short
- SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration count ${sv.itera
- 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/ac5c0cff8e1eb6f5.json.
Report an issue: GitHub.