jackc/pgx · error

too many values

Error message

too many values

What it means

Returned by DataRow.Encode when the Values slice has more than 65535 entries. The field count is encoded as a uint16, so MaxUint16 is the hard ceiling. The guard prevents a silently-truncated count that would make the receiver misread the row. DataRow is the 'D' message carrying one row's column values.

Solutions

  1. Bound the Values slice to 65535 entries before encoding; if you genuinely have more, the wire protocol cannot carry it in one DataRow.
  2. Audit the loop that builds Values for accidental duplication or mis-scoping.
  3. If serialising a struct/map, cap or chunk the columns and reconsider the schema (PostgreSQL itself limits columns to ~1600 per table).
  4. Add a pre-encode length check returning a clear error to the caller.

Example fix

// before
row := &pgproto3.DataRow{Values: allValues} // len > 65535
_, err := row.Encode(nil)

// after
if len(allValues) > 65535 {
    return fmt.Errorf("too many columns: %d (max 65535)", len(allValues))
}
row := &pgproto3.DataRow{Values: allValues}
_, err := row.Encode(nil)
Defensive patterns

Strategy: validation

Validate before calling

func validateDataRowEncode(r *pgproto3.DataRow) error {
	if len(r.Values) > math.MaxUint16 {
		return fmt.Errorf("too many values: %d (max %d)", len(r.Values), math.MaxUint16)
	}
	return nil
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Calling `(*DataRow).Encode(dst)` with `len(Values) > 65535`. This is a client→server message in the extended-query path, so it can be hit by application code constructing a row with an enormous column count.

Common situations: A caller loops over a map or struct and appends one value per key without bounding the count, or a bug duplicates entries. Real-world tables almost never have >64k columns, so this usually signals a construction bug rather than a legitimate wide row.

Related errors


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

Appendix: source

Thrown at pgproto3/data_row.go:69

		} else {
			if len(src[rp:]) < valueLen || valueLen < 0 {
				return &invalidMessageFormatErr{messageType: "DataRow"}
			}

			dst.Values[i] = src[rp : rp+valueLen : rp+valueLen]
			rp += valueLen
		}
	}

	return nil
}

// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
func (src *DataRow) Encode(dst []byte) ([]byte, error) {
	dst, sp := beginMessage(dst, 'D')

	if len(src.Values) > math.MaxUint16 {
		return nil, errors.New("too many values")
	}
	dst = pgio.AppendUint16(dst, uint16(len(src.Values)))
	for _, v := range src.Values {
		if v == nil {
			dst = pgio.AppendInt32(dst, -1)
			continue
		}

		dst = pgio.AppendInt32(dst, int32(len(v)))
		dst = append(dst, v...)
	}

	return finishMessage(dst, sp)
}

// MarshalJSON implements encoding/json.Marshaler.
func (src DataRow) MarshalJSON() ([]byte, error) {
	formattedValues := make([]map[string]string, len(src.Values))

View on GitHub (pinned to ec1a0befd2)