jackc/pgx · error
channel binding required but channel binding data is not ava
Error message
channel binding required but channel binding data is not available
What it means
Returned by (*PgConn).scramAuth when Config.ChannelBinding == "require" but sc.channelBindingData is still nil after the TLS branch. Channel binding data is the server certificate hash obtained via getTLSCertificateHash; if the connection is not TLS or the hash could not be derived, requiring binding is impossible, so the client aborts rather than silently authenticating without the protection the caller asked for.
Source
Thrown at pgconn/auth_scram.go:72
// If we have a TLS connection and channel binding is not disabled, attempt to
// extract the server certificate hash for tls-server-end-point channel binding.
if tlsConn, ok := c.conn.(*tls.Conn); ok && c.config.ChannelBinding != "disable" {
certHash, err := getTLSCertificateHash(tlsConn)
if err != nil && c.config.ChannelBinding == "require" {
return fmt.Errorf("channel binding required but failed to get server certificate hash: %w", err)
}
// Upgrade to SCRAM-SHA-256-PLUS if we have binding data and the server supports it.
if certHash != nil && serverHasPlus {
sc.authMechanism = scramSHA256PlusName
}
sc.channelBindingData = certHash
sc.hasTLS = true
}
if c.config.ChannelBinding == "require" && sc.channelBindingData == nil {
return errors.New("channel binding required but channel binding data is not available")
}
// Send client-first-message in a SASLInitialResponse
saslInitialResponse := &pgproto3.SASLInitialResponse{
AuthMechanism: sc.authMechanism,
Data: sc.clientFirstMessage(),
}
c.frontend.Send(saslInitialResponse)
err = c.flushWithPotentialWriteReadDeadlock()
if err != nil {
return err
}
// Receive server-first-message payload in an AuthenticationSASLContinue.
saslContinue, err := c.rxSASLContinue()
if err != nil {
return err
}View on GitHub (pinned to ec1a0befd2)
Solutions
- Enable TLS on the connection (sslmode=require/verify-ca/verify-full) so a server certificate hash can be derived.
- If TLS is genuinely unavailable, relax Config.ChannelBinding to "" or "disable".
- Verify the server presents a certificate whose signature algorithm is supported by getTLSCertificateHash (RSA/ECDSA SHA-256/384/512).
Example fix
// before: channel binding required over plaintext cc.ChannelBinding = "require" // conn string has sslmode=disable // after: require TLS so binding data is available cc.ChannelBinding = "require" // conn string: sslmode=verify-full
Defensive patterns
Strategy: validation
Validate before calling
// Ensure TLS is on before requiring channel binding.
func validateBindingNeedsTLS(channelBinding, sslmode string) error {
if channelBinding == "require" && (sslmode == "" || sslmode == "disable") {
return errors.New("ChannelBinding=require needs TLS (sslmode != disable)")
}
return nil
} Try / catch
if err := connect(); err != nil {
if strings.Contains(err.Error(), "channel binding required but channel binding data is not available") {
cc.ChannelBinding = "" // relax and retry over the same TLS/non-TLS link
}
} Prevention
- Pair ChannelBinding="require" with sslmode=verify-full.
- Confirm the server presents a certificate whose signature algorithm getTLSCertificateHash supports.
- Don't require binding over plaintext internal links.
When it happens
Trigger: Config.ChannelBinding == "require" on a plaintext connection (no TLS), or on a TLS connection where getTLSCertificateHash failed non-fatally (certHash nil and ChannelBinding != "require" path left it nil). Most directly: requiring channel binding over a non-TLS socket.
Common situations: Forgetting sslmode/SSL when ChannelBinding="require"; mismatched expectations where ops set ChannelBinding=require but the deployment uses plaintext internal transport.
Related errors
- channel binding required but server does not support SCRAM-S
- invalid SCRAM ServerSignature received from server
- no peer certificates for channel binding
- invalid SCRAM server-first-message received from server: did
- invalid SCRAM server-first-message received from server: did
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/f21337a7d4e58ce3.json.
Report an issue: GitHub.