{"id":"bd022fa0a2c0d552","repo":"jackc/pgx","slug":"too-many-values","errorCode":null,"errorMessage":"too many values","messagePattern":"too many values","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pgproto3/data_row.go","lineNumber":69,"sourceCode":"\t\t} else {\n\t\t\tif len(src[rp:]) < valueLen || valueLen < 0 {\n\t\t\t\treturn &invalidMessageFormatErr{messageType: \"DataRow\"}\n\t\t\t}\n\n\t\t\tdst.Values[i] = src[rp : rp+valueLen : rp+valueLen]\n\t\t\trp += valueLen\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.\nfunc (src *DataRow) Encode(dst []byte) ([]byte, error) {\n\tdst, sp := beginMessage(dst, 'D')\n\n\tif len(src.Values) > math.MaxUint16 {\n\t\treturn nil, errors.New(\"too many values\")\n\t}\n\tdst = pgio.AppendUint16(dst, uint16(len(src.Values)))\n\tfor _, v := range src.Values {\n\t\tif v == nil {\n\t\t\tdst = pgio.AppendInt32(dst, -1)\n\t\t\tcontinue\n\t\t}\n\n\t\tdst = pgio.AppendInt32(dst, int32(len(v)))\n\t\tdst = append(dst, v...)\n\t}\n\n\treturn finishMessage(dst, sp)\n}\n\n// MarshalJSON implements encoding/json.Marshaler.\nfunc (src DataRow) MarshalJSON() ([]byte, error) {\n\tformattedValues := make([]map[string]string, len(src.Values))","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/jackc/pgx/blob/ec1a0befd22592cffffdeeb0a50311b506372f4c/pgproto3/data_row.go#L51-L87","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Bound the Values slice to 65535 entries before encoding; if you genuinely have more, the wire protocol cannot carry it in one DataRow.","Audit the loop that builds Values for accidental duplication or mis-scoping.","If serialising a struct/map, cap or chunk the columns and reconsider the schema (PostgreSQL itself limits columns to ~1600 per table).","Add a pre-encode length check returning a clear error to the caller."],"exampleFix":"// before\nrow := &pgproto3.DataRow{Values: allValues} // len > 65535\n_, err := row.Encode(nil)\n\n// after\nif len(allValues) > 65535 {\n    return fmt.Errorf(\"too many columns: %d (max 65535)\", len(allValues))\n}\nrow := &pgproto3.DataRow{Values: allValues}\n_, err := row.Encode(nil)","handlingStrategy":"validation","validationCode":"func validateDataRowEncode(r *pgproto3.DataRow) error {\n\tif len(r.Values) > math.MaxUint16 {\n\t\treturn fmt.Errorf(\"too many values: %d (max %d)\", len(r.Values), math.MaxUint16)\n\t}\n\treturn nil\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Bound Values at 65535 before encoding; PostgreSQL tables cap at ~1600 columns.","Audit construction loops for accidental duplication.","Chunk excessively wide rows or redesign the schema."],"tags":["pgproto3","protocol","encoding","data-row","wire-protocol","validation"],"analyzedSha":"ec1a0befd22592cffffdeeb0a50311b506372f4c","analyzedAt":"2026-08-04T22:52:11.263Z","schemaVersion":2}