brianc/node-postgres · error · Error

Invalid sslnegotiation value: "${this.sslnegotiation}". Vali

Error message

Invalid sslnegotiation value: "${this.sslnegotiation}". Valid values are "postgres" and "direct".

What it means

Thrown by the ConnectionParameters constructor (connection-parameters.js:105-108) when the sslnegotiation setting is set to a value other than 'postgres' or 'direct' (or undefined). sslnegotiation controls how the client initiates TLS: 'postgres' (default) uses the traditional SSLRequest packet, 'direct' begins the TLS handshake immediately. An unrecognized value indicates a typo or a setting from a different client library. The value can come from config.sslnegotiation or the PGSSLNEGOTIATION environment variable.

Source

Thrown at packages/pg/lib/connection-parameters.js:106

      if (this.ssl === 'true') {
        this.ssl = true
      }
    }
    // support passing in ssl=no-verify via connection string
    if (this.ssl === 'no-verify') {
      this.ssl = { rejectUnauthorized: false }
    }
    if (this.ssl && this.ssl.key) {
      Object.defineProperty(this.ssl, 'key', {
        enumerable: false,
      })
    }

    // How to negotiate SSL: 'postgres' (default, the traditional SSLRequest
    // handshake) or 'direct' (start the TLS handshake immediately on connect).
    this.sslnegotiation = val('sslnegotiation', config, 'PGSSLNEGOTIATION')
    if (this.sslnegotiation !== undefined && this.sslnegotiation !== 'postgres' && this.sslnegotiation !== 'direct') {
      throw new Error(
        `Invalid sslnegotiation value: "${this.sslnegotiation}". Valid values are "postgres" and "direct".`
      )
    }
    if (this.sslnegotiation === 'direct' && !this.ssl) {
      throw new Error('sslnegotiation=direct requires SSL to be enabled')
    }

    this.client_encoding = val('client_encoding', config)
    this.replication = val('replication', config)
    // a domain socket begins with '/'
    this.isDomainSocket = !(this.host || '').indexOf('/')

    this.application_name = val('application_name', config, 'PGAPPNAME')
    this.fallback_application_name = val('fallback_application_name', config, false)
    this.statement_timeout = val('statement_timeout', config, false)
    this.lock_timeout = val('lock_timeout', config, false)
    this.idle_in_transaction_session_timeout = val('idle_in_transaction_session_timeout', config, false)
    this.query_timeout = val('query_timeout', config, false)

View on GitHub (pinned to c5e8c9a57b)

Solutions

  1. Set sslnegotiation to 'postgres' (default, SSLRequest handshake) or 'direct' (immediate TLS).
  2. If you do not need direct TLS negotiation, remove the sslnegotiation setting entirely to use the default.
  3. Check the PGSSLNEGOTIATION environment variable in your deployment environment and correct or unset it.

Example fix

// before
const client = new Client({ ssl: true, sslnegotiation: 'prefer' });

// after
const client = new Client({ ssl: true, sslnegotiation: 'direct' });
// or omit it for the default
const client = new Client({ ssl: true });
Defensive patterns

Strategy: validation

Validate before calling

const VALID_SSL_NEGOTIATION = ['postgres', 'direct', undefined];

function validateSslNegotiation(config) {
  const val = config.sslnegotiation ?? process.env.PGSSLNEGOTIATION;
  if (!VALID_SSL_NEGOTIATION.includes(val)) {
    throw new Error(
      `sslnegotiation '${val}' is invalid. Use 'postgres' or 'direct', or omit it.`
    );
  }
}

Type guard

function isSslNegotiation(v) {
  return v === undefined || v === 'postgres' || v === 'direct';
}

Prevention

When it happens

Trigger: Passing { sslnegotiation: 'prefer' } or setting PGSSLNEGOTIATION=auto. Any value that is not undefined, 'postgres', or 'direct' triggers the throw at line 106.

Common situations: Confusing sslmode values (prefer/require/verify-full) with sslnegotiation values. Setting PGSSLNEGOTIATION to an invalid string in a deployment manifest. Copying a configuration from a different PostgreSQL driver that supports different negotiation modes.

Related errors


AI-assisted analysis of brianc/node-postgres@c5e8c9a57b (2026-08-03). Data as JSON: /data/errors/606d6a69b912f053.json. Report an issue: GitHub.