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

  1. Confirm the endpoint is genuine, conformant PostgreSQL.
  2. Remove any SASL-rewriting middleware.
  3. 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

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


AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04). Data as JSON: /data/errors/f25c5e25ee35776e.json. Report an issue: GitHub.