{"id":"54414192ecfaacc4","repo":"jackc/pgx","slug":"channel-binding-required-but-server-does-not-suppo","errorCode":null,"errorMessage":"channel binding required but server does not support SCRAM-SHA-256-PLUS","messagePattern":"channel binding required but server does not support SCRAM-SHA-256-PLUS","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pgconn/auth_scram.go","lineNumber":51,"sourceCode":"\t\"golang.org/x/text/secure/precis\"\n)\n\nconst (\n\tclientNonceLen      = 18\n\tscramSHA256Name     = \"SCRAM-SHA-256\"\n\tscramSHA256PlusName = \"SCRAM-SHA-256-PLUS\"\n)\n\n// Perform SCRAM authentication.\nfunc (c *PgConn) scramAuth(serverAuthMechanisms []string) error {\n\tsc, err := newScramClient(serverAuthMechanisms, c.config.Password)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tserverHasPlus := slices.Contains(sc.serverAuthMechanisms, scramSHA256PlusName)\n\tif c.config.ChannelBinding == \"require\" && !serverHasPlus {\n\t\treturn errors.New(\"channel binding required but server does not support SCRAM-SHA-256-PLUS\")\n\t}\n\n\t// If we have a TLS connection and channel binding is not disabled, attempt to\n\t// extract the server certificate hash for tls-server-end-point channel binding.\n\tif tlsConn, ok := c.conn.(*tls.Conn); ok && c.config.ChannelBinding != \"disable\" {\n\t\tcertHash, err := getTLSCertificateHash(tlsConn)\n\t\tif err != nil && c.config.ChannelBinding == \"require\" {\n\t\t\treturn fmt.Errorf(\"channel binding required but failed to get server certificate hash: %w\", err)\n\t\t}\n\n\t\t// Upgrade to SCRAM-SHA-256-PLUS if we have binding data and the server supports it.\n\t\tif certHash != nil && serverHasPlus {\n\t\t\tsc.authMechanism = scramSHA256PlusName\n\t\t}\n\n\t\tsc.channelBindingData = certHash\n\t\tsc.hasTLS = true\n\t}","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/jackc/pgx/blob/ec1a0befd22592cffffdeeb0a50311b506372f4c/pgconn/auth_scram.go#L33-L69","documentation":"Returned by (*PgConn).scramAuth when Config.ChannelBinding == \"require\" but the server's advertised SASL mechanisms do not include SCRAM-SHA-256-PLUS. The PLUS variant carries tls-server-end-point channel binding (RFC 5929); without it the client refuses to proceed to prevent MITM downgrade attacks.","triggerScenarios":"Config.ChannelBinding set to \"require\" while connecting to a server that only advertises SCRAM-SHA-256 (no PLUS). Happens over a TLS connection where the client demands binding but the server doesn't support it, or when an intermediary strips the PLUS advertisement.","commonSituations":"Hardening a connection with ChannelBinding=\"require\" against an older PostgreSQL (< supports PLUS) or a connection-pooler (PgBouncer in some modes) that doesn't forward PLUS; TLS-terminating proxies that drop the mechanism.","solutions":["If binding is optional, leave Config.ChannelBinding unset (auto) or set \"disable\" so auth falls back to plain SCRAM-SHA-256.","If binding is mandatory, upgrade/reconfigure the server or pooler to advertise SCRAM-SHA-256-PLUS and ensure TLS is end-to-end.","Remove any TLS-terminating proxy between client and server so the server's certificate is presented directly."],"exampleFix":"// before\ncc.ChannelBinding = \"require\"\n\n// after (auto: uses PLUS when available, plain SCRAM otherwise)\ncc.ChannelBinding = \"\"","handlingStrategy":"validation","validationCode":"// Decide channel binding policy based on what the deployment supports.\nfunc resolveChannelBinding(wantRequire bool, serverSupportsPlus bool) string {\n    if wantRequire && !serverSupportsPlus {\n        // fall back instead of failing at connect time\n        return \"\" // auto\n    }\n    if wantRequire {\n        return \"require\"\n    }\n    return \"\"\n}","typeGuard":null,"tryCatchPattern":"err := conn.Ping(ctx)\nif err != nil && strings.Contains(err.Error(), \"channel binding required but server does not support\") {\n    cc.ChannelBinding = \"\" // relax and reconnect\n}","preventionTips":["Prefer leaving ChannelBinding unset so pgx auto-uses PLUS when available.","Only set \"require\" when you control the server and know PLUS is advertised end-to-end.","Eliminate TLS-terminating proxies that strip the PLUS mechanism."],"tags":["authentication","scram","channel-binding","tls","security"],"analyzedSha":"ec1a0befd22592cffffdeeb0a50311b506372f4c","analyzedAt":"2026-08-04T22:52:11.263Z","schemaVersion":2}