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

  1. Verify the host:port actually points at a PostgreSQL server (psql connects cleanly).
  2. If behind a proxy/pooler, bypass it temporarily to confirm the handshake; check the proxy logs for frame corruption.
  3. Enable TLS or fix the broken TLS terminator so the auth frame cannot be corrupted in flight.
  4. 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

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


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