jackc/pgx · error
invalid length
Error message
invalid length
What it means
ErrInvalidLength is the sentinel (internal/pgio/read.go:213) wrapped by the Uint16Exact/Uint32Exact/Uint64Exact helpers when src is not exactly 2/4/8 bytes. These helpers are the scan plans for fixed-size built-in types (int2/int4/int8/float4/float8 and friends); they assert the server's binary payload length matches the type size, since for an unstructured scalar there is nothing else to check.
Source
Thrown at internal/pgio/read.go:213
// Finish returns the first error encountered, or an error if unread bytes
// remain. Decoders that must consume the entire source should end with Finish.
func (r *Reader) Finish() error {
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))View on GitHub (pinned to ec1a0befd2)
Solutions
- Confirm the column type OID is mapped to the correct codec in your TypeMap (a wrong OID→codec mapping produces wrong-length reads).
- Capture the failing column's typname and the raw src length to confirm the server payload is genuinely mis-sized.
- Update pgx to a release matching your server version.
- For custom scalars, do not reuse the *Exact helpers unless your binary width is exactly 2/4/8; write a sized Codec instead.
Example fix
// before — wrong exact helper for a custom 16-byte type
plans := pgtype.ScanPlanFuncs{}
plans.Register(oid, func(m *pgtype.Map, src []byte) (any, error) {
return pgio.Uint32Exact(src) // wrong size -> "invalid length"
})
// after — sized codec matching the real binary width
func (c *MyCodec) DecodeBinary(m *pgtype.Map, src []byte) (any, error) {
if len(src) != 16 { return nil, fmt.Errorf("bad len %d", len(src)) }
/* decode 16 bytes */
} Defensive patterns
Strategy: try-catch
Type guard
func isInvalidLength(err error) bool { return errors.Is(err, pgio.ErrInvalidLength) } Try / catch
v, err := plan.Scan(typeMap, src)
if errors.Is(err, pgio.ErrInvalidLength) {
// wrong-length binary payload for a fixed-size type
log.Printf("invalid length for oid=%d: got %d bytes", oid, len(src))
return nil, err
} Prevention
- Verify OID→codec mappings in your TypeMap.
- Do not reuse Uint*Exact helpers for non-2/4/8-byte types.
- Match pgx version to server version.
- For custom scalars, write a Codec that validates len(src).
When it happens
Trigger: Scanning a fixed-size scalar column whose binary representation arrived with the wrong byte length: e.g. an int4 column with a 3- or 8-byte payload, or NULL handled incorrectly so an empty/foreign slice is passed to the Exact helper.
Common situations: Server/extension bug returning a wrong-length payload; a codec/type-map misregistration pointing an OID at the wrong Exact helper (e.g. int8 OID mapped to Uint32Exact); corrupted bytes from a proxy; misuse of a custom Codec that forwards the wrong src.
Related errors
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/66dc66e4a2e31780.json.
Report an issue: GitHub.