jackc/pgx · error · ErrInvalidLength

: expected bytes, got

Error message

%w: expected %d bytes, got %d

What it means

An exact-length read helper (Uint16Exact/Uint32Exact/Uint64Exact) found the source size differs from the fixed size required for the value. Wraps ErrInvalidLength; the message body must be exactly the fixed-width value.

Solutions

  1. Ensure the buffer passed to the Exact readers contains exactly the fixed-size value
  2. Check for extra or missing bytes around the value in the frame
  3. Use the non-Exact readers when the value is embedded in a larger message
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at internal/pgio/read.go:216 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at internal/pgio/read.go:216

	if r.err != nil {
		return r.err
	}
	if r.rp != len(r.s) {
		return r.errTrailing()
	}
	return nil
}

func (r *Reader) errTrailing() error {
	return fmt.Errorf("%d unexpected trailing bytes at offset %d", len(r.s)-r.rp, r.rp)
}

// ErrInvalidLength is wrapped by the errors returned from the exact-length
// read functions below.
var ErrInvalidLength = errors.New("invalid length")

func errLength(want, got int) error {
	return fmt.Errorf("%w: expected %d bytes, got %d", ErrInvalidLength, want, got)
}

// The Uint*Exact functions read a single fixed-size value that makes up an
// entire message, which is what the scan plans for the fixed-size PostgreSQL
// types receive. They are the counterpart to Reader for values that have no
// internal structure: there is no position to track and no error to make
// sticky, just an exact-length assertion the caller cannot skip. Keeping them
// separate from Reader is deliberate — these are the hottest decode paths in
// the driver and they are small enough for the compiler to inline, which a
// Reader method carrying a bounds check and a read pointer is not.

// Uint16Exact returns the big-endian uint16 in src, which must be exactly 2 bytes.
func Uint16Exact(src []byte) (uint16, error) {
	if len(src) != 2 {
		return 0, errLength(2, len(src))
	}
	return binary.BigEndian.Uint16(src), nil
}

View on GitHub (pinned to ec1a0befd2)