jackc/pgx · error
bad authentication message size
Error message
bad authentication message size
What it means
Returned by AuthenticationCleartextPassword.Decode in pgproto3/authentication_cleartext_password.go:24 when the body of an 'R' (Authentication) message is not exactly 4 bytes. This message carries only the 4-byte auth-type code (AuthTypeCleartextPassword = 3) and nothing else, so any other length is a protocol violation. In the normal client path it is essentially unreachable because the frontend reads exactly bodyLen bytes and dispatch is driven by that same 4-byte code; it surfaces when the bytes are corrupted or when Decode is invoked directly on untrusted data (proxies, fuzzing, mock servers).
Source
Thrown at pgproto3/authentication_cleartext_password.go:24
"errors"
"github.com/jackc/pgx/v5/internal/pgio"
)
// AuthenticationCleartextPassword is a message sent from the backend indicating that a clear-text password is required.
type AuthenticationCleartextPassword struct{}
// Backend identifies this message as sendable by the PostgreSQL backend.
func (*AuthenticationCleartextPassword) Backend() {}
// Backend identifies this message as an authentication response.
func (*AuthenticationCleartextPassword) AuthenticationResponse() {}
// Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
// type identifier and 4 byte message length.
func (dst *AuthenticationCleartextPassword) Decode(src []byte) error {
if len(src) != 4 {
return errors.New("bad authentication message size")
}
authType := binary.BigEndian.Uint32(src)
if authType != AuthTypeCleartextPassword {
return errors.New("bad auth type")
}
return nil
}
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
func (src *AuthenticationCleartextPassword) Encode(dst []byte) ([]byte, error) {
dst, sp := beginMessage(dst, 'R')
dst = pgio.AppendUint32(dst, AuthTypeCleartextPassword)
return finishMessage(dst, sp)
}
View on GitHub (pinned to ec1a0befd2)
Solutions
- Verify the host:port actually points at a PostgreSQL server (psql connects cleanly).
- If behind a proxy/pooler, bypass it temporarily to confirm the handshake; check the proxy logs for frame corruption.
- Enable TLS or fix the broken TLS terminator so the auth frame cannot be corrupted in flight.
- When using pgproto3 directly, validate message length against the protocol before calling Decode.
Example fix
// direct pgproto3 usage: validate before decode
if len(body) != 4 {
return fmt.Errorf("rejecting malformed cleartext auth frame: len=%d", len(body))
}
var m pgproto3.AuthenticationCleartextPassword
if err := m.Decode(body); err != nil { return err } Defensive patterns
Strategy: try-catch
Validate before calling
// Before connecting, sanity-check that the endpoint speaks PostgreSQL.
// psql -h host -p port -U user -d db should succeed; or probe with a tiny net.Dial.
conn, err := pgconn.Connect(ctx, connString)
if err != nil { /* err wraps "bad authentication message size" */ } Try / catch
conn, err := pgconn.Connect(ctx, connString)
if err != nil {
if strings.Contains(err.Error(), "bad authentication message size") {
// endpoint is not a well-behaved PostgreSQL server / frame was corrupted
return fmt.Errorf("invalid PostgreSQL handshake at %s: %w", connString, err)
}
return err
} Prevention
- Point the connection string at a verified PostgreSQL host:port.
- Prefer TLS (sslmode) to prevent in-flight frame corruption.
- Bypass or fix proxies/poolers that mangle the startup handshake.
- When using pgproto3 directly, assert len(body)==4 before AuthenticationCleartextPassword.Decode.
When it happens
Trigger: A server or intermediary sends an AuthenticationCleartextPassword 'R' message whose declared length is not 8 total (4 length + 4 type). Causes: a truncated/mangled TCP stream, a TLS-terminating proxy corrupting the frame, a non-PostgreSQL service (HTTP health check, wrong-port service) replying with arbitrary bytes that happen to parse as 'R', or direct pgproto3.Decode usage on hand-built bytes.
Common situations: Connecting to the wrong port (e.g. an HTTP/Redis server) whose greeting bytes align with 'R'; a misconfigured PgBouncer/HAProxy mangling the startup handshake; packet corruption on a flaky link; calling pgproto3 in a custom proxy/mock-server on attacker-controlled input.
Related errors
- bad auth type
- bad authentication message size
- bad authentication message size
- authentication message too short
- authentication message too short
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/94e791288ec562f1.json.
Report an issue: GitHub.