jackc/pgx · error
too many column format codes
Error message
too many column format codes
What it means
Returned by CopyInResponse.Encode when ColumnFormatCodes has more than 65535 entries. The column count is encoded as a uint16, so values beyond MaxUint16 cannot fit. The guard avoids silently truncating the count. CopyInResponse is the 'G' message the server sends to begin a COPY FROM STDIN (client→server bulk load) operation.
Source
Thrown at pgproto3/copy_in_response.go:53
}
columnFormatCodes := make([]uint16, columnCount)
for i := range columnCount {
columnFormatCodes[i] = binary.BigEndian.Uint16(buf.Next(2))
}
*dst = CopyInResponse{OverallFormat: overallFormat, ColumnFormatCodes: columnFormatCodes}
return nil
}
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
func (src *CopyInResponse) Encode(dst []byte) ([]byte, error) {
dst, sp := beginMessage(dst, 'G')
dst = append(dst, src.OverallFormat)
if len(src.ColumnFormatCodes) > math.MaxUint16 {
return nil, errors.New("too many column format codes")
}
dst = pgio.AppendUint16(dst, uint16(len(src.ColumnFormatCodes)))
for _, fc := range src.ColumnFormatCodes {
dst = pgio.AppendUint16(dst, fc)
}
return finishMessage(dst, sp)
}
// MarshalJSON implements encoding/json.Marshaler.
func (src CopyInResponse) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type string
ColumnFormatCodes []uint16
}{
Type: "CopyInResponse",
ColumnFormatCodes: src.ColumnFormatCodes,
})View on GitHub (pinned to ec1a0befd2)
Solutions
- Cap ColumnFormatCodes at 65535; a single-entry slice is valid and applies the format to all columns.
- Audit the construction loop for an unbounded or mis-scoped append.
- If proxying, forward the server's raw encoded bytes instead of decoding and re-encoding.
- Verify the column count source is not a corrupted value read from elsewhere.
Example fix
// before
resp := &pgproto3.CopyInResponse{
OverallFormat: 0,
ColumnFormatCodes: bigSlice, // > 65535
}
_, err := resp.Encode(nil)
// after
resp := &pgproto3.CopyInResponse{
OverallFormat: 0,
ColumnFormatCodes: []uint16{0},
}
_, err := resp.Encode(nil) Defensive patterns
Strategy: validation
Validate before calling
func validateCopyInResponseEncode(r *pgproto3.CopyInResponse) error {
if len(r.ColumnFormatCodes) > math.MaxUint16 {
return fmt.Errorf("too many column format codes: %d (max %d)", len(r.ColumnFormatCodes), math.MaxUint16)
}
return nil
} Type guard
null
Try / catch
null
Prevention
- Use a one-element ColumnFormatCodes slice for uniform formats.
- Cap column counts at 65535.
- Forward server bytes verbatim in proxies.
When it happens
Trigger: Calling `(*CopyInResponse).Encode(dst)` with `len(ColumnFormatCodes) > 65535`. CopyInResponse is a server-originated message, so this only fires in a proxy/server/test harness synthesising one, never in a normal pgx client.
Common situations: A PostgreSQL-compatible proxy or test server builds a CopyInResponse with a per-column format slice for an artificially wide table (>64k columns). A loop that appends format codes per-row instead of per-column can also blow the limit.
Related errors
- too many column format codes
- too many column format codes
- secret key too long
- too many values
- too many arg format codes
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/e565f321639b6cc2.json.
Report an issue: GitHub.