jackc/pgx · error
invalid SCRAM server-final-message received from server
Error message
invalid SCRAM server-final-message received from server
What it means
Returned by recvServerFinalMessage when the SCRAM server-final-message does not begin with 'v=' (the ServerSignature attribute). Per RFC 5802 the server-final-message is 'v=<signature>' optionally preceded by an 'e=' error attribute; pgx expects 'v=' here because auth errors arrive as ErrorResponse earlier.
Source
Thrown at pgconn/auth_scram.go:335
}
channelBindingEncoded := base64.StdEncoding.EncodeToString(channelBindInput)
clientFinalMessageWithoutProof := fmt.Appendf(nil, "c=%s,r=%s", channelBindingEncoded, sc.clientAndServerNonce)
var err error
sc.saltedPassword, err = pbkdf2.Key(sha256.New, sc.password, sc.salt, sc.iterations, 32)
if err != nil {
panic(err) // This should never happen.
}
sc.authMessage = bytes.Join([][]byte{sc.clientFirstMessageBare, sc.serverFirstMessage, clientFinalMessageWithoutProof}, []byte(","))
clientProof := computeClientProof(sc.saltedPassword, sc.authMessage)
return fmt.Sprintf("%s,p=%s", clientFinalMessageWithoutProof, clientProof)
}
func (sc *scramClient) recvServerFinalMessage(serverFinalMessage []byte) error {
if !bytes.HasPrefix(serverFinalMessage, []byte("v=")) {
return errors.New("invalid SCRAM server-final-message received from server")
}
serverSignature := serverFinalMessage[2:]
if !hmac.Equal(serverSignature, computeServerSignature(sc.saltedPassword, sc.authMessage)) {
return errors.New("invalid SCRAM ServerSignature received from server")
}
return nil
}
func computeHMAC(key, msg []byte) []byte {
mac := hmac.New(sha256.New, key)
mac.Write(msg)
return mac.Sum(nil)
}
func computeClientProof(saltedPassword, authMessage []byte) []byte {View on GitHub (pinned to ec1a0befd2)
Solutions
- Confirm the endpoint is genuine, conformant PostgreSQL.
- Remove any SASL-rewriting middleware.
- Capture the AuthenticationSASLFinal payload and report the malformed message.
Defensive patterns
Strategy: try-catch
Try / catch
if err := connect(); err != nil && strings.Contains(err.Error(), "invalid SCRAM server-final-message") {
return fmt.Errorf("malformed SCRAM final message from server: %w", err)
} Prevention
- Use sslmode=verify-full so the final message cannot be tampered with.
- Avoid proxies that rewrite SASL payloads.
- Capture AuthenticationSASLFinal bytes to localize the defect.
When it happens
Trigger: Server sends an AuthenticationSASLFinal whose payload lacks the 'v=' prefix. Indicates a malformed/tampered final message or a non-conformant server.
Common situations: Buggy server/proxy corrupting the final SASL message; MITM tampering; rare server bugs.
Related errors
- invalid SCRAM server-first-message received from server: did
- invalid SCRAM server-first-message received from server: did
- invalid SCRAM server-first-message received from server: did
- invalid SCRAM nonce: did not start with client nonce
- invalid SCRAM nonce: did not include server nonce
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/f25c5e25ee35776e.json.
Report an issue: GitHub.