jackc/pgx · error
too many parameter format codes
Error message
too many parameter format codes
What it means
Returned by Bind.Encode in pgproto3/bind.go:122 when len(src.ParameterFormatCodes) exceeds 65535 (math.MaxUint16). The wire protocol encodes the parameter-format-code count as a uint16, so more than 65535 codes cannot be serialized. This is a caller-side guard fired while building the Bind message to send to the server, before any network I/O.
Source
Thrown at pgproto3/bind.go:122
for i := range resultFormatCodeCount {
dst.ResultFormatCodes[i] = int16(binary.BigEndian.Uint16(src[rp:]))
rp += 2
}
return nil
}
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
func (src *Bind) Encode(dst []byte) ([]byte, error) {
dst, sp := beginMessage(dst, 'B')
dst = append(dst, src.DestinationPortal...)
dst = append(dst, 0)
dst = append(dst, src.PreparedStatement...)
dst = append(dst, 0)
if len(src.ParameterFormatCodes) > math.MaxUint16 {
return nil, errors.New("too many parameter format codes")
}
dst = pgio.AppendUint16(dst, uint16(len(src.ParameterFormatCodes)))
for _, fc := range src.ParameterFormatCodes {
dst = pgio.AppendInt16(dst, fc)
}
if len(src.Parameters) > math.MaxUint16 {
return nil, errors.New("too many parameters")
}
dst = pgio.AppendUint16(dst, uint16(len(src.Parameters)))
for _, p := range src.Parameters {
if p == nil {
dst = pgio.AppendInt32(dst, -1)
continue
}
dst = pgio.AppendInt32(dst, int32(len(p)))
dst = append(dst, p...)View on GitHub (pinned to ec1a0befd2)
Solutions
- Cap ParameterFormatCodes at 65535; for uniform formats use a single code (the protocol applies one code to all params when count is 1).
- Batch the operation: split the query into chunks of <=65535 parameters.
- For bulk inserts, use COPY (pgx CopyFrom) instead of parameterized inserts.
Example fix
// before: one format code per parameter, blows past 65535
formats := make([]int16, 100000) // -> "too many parameter format codes"
// after: a single code applies to all parameters (protocol rule)
formats := []int16{0} // text format for every parameter Defensive patterns
Strategy: validation
Validate before calling
const maxFormatCodes = 65535 // math.MaxUint16
if len(parameterFormatCodes) > maxFormatCodes {
// Use a single code: the protocol applies one code to ALL parameters.
parameterFormatCodes = []int16{parameterFormatCodes[0]}
} Type guard
func bindFormatCodesOK(codes []int16) bool { return len(codes) <= 65535 } Try / catch
if _, err := bindMsg.Encode(dst); err != nil {
if strings.Contains(err.Error(), "too many parameter format codes") {
// collapse to a single uniform code, or split the batch
bindMsg.ParameterFormatCodes = []int16{bindMsg.ParameterFormatCodes[0]}
}
} Prevention
- Use at most one ParameterFormatCode when all parameters share a format (protocol applies it to all).
- Split large batches so each Bind carries <=65535 entries.
- Add a unit assertion that generated format-code slices stay under 65535.
When it happens
Trigger: Constructing a Bind (or an extended-query ExecParams/ExecPrepared/Batch) with more than 65535 parameter format codes. In practice this means an explicit ParameterFormatCodes slice exceeding the limit, almost always an application bug since pgx normally generates at most one code per parameter.
Common situations: A query with an enormous IN-list or bulk insert built with >65535 placeholders; programmatically generating format codes in a loop without a cap; copying a result-set column count into format codes by mistake.
Related errors
- too many parameters
- too many result format codes
- bad authentication message size
- bad auth type
- authentication message too short
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/165ae3669eacc1ca.json.
Report an issue: GitHub.