go-kratos/kratos · warning
too many values for field %q: %s
Error message
too many values for field %q: %s
What it means
Form-binding decoder error for a singular field: the field resolved by the path is neither a list nor a map (the switch's IsList/IsMap cases do not apply), but more than one form value was supplied for that single key. The message lists the field name and all received values joined by commas.
Source
Thrown at encoding/form/proto_decode.go:79
}
return fmt.Errorf("invalid path: %q is not a message", fieldName)
}
v = v.Mutable(fd).Message()
}
if of := fd.ContainingOneof(); of != nil {
if f := v.WhichOneof(of); f != nil {
return fmt.Errorf("field already set for oneof %q", of.FullName().Name())
}
}
switch {
case fd.IsList():
return populateRepeatedField(fd, v.Mutable(fd).List(), values)
case fd.IsMap():
return populateMapField(fd, v.Mutable(fd).Map(), fieldPath, values)
}
if len(values) > 1 {
return fmt.Errorf("too many values for field %q: %s", fd.FullName().Name(), strings.Join(values, ", "))
}
return populateField(fd, v, values[0])
}
func getFieldDescriptor(v protoreflect.Message, fieldName string) protoreflect.FieldDescriptor {
var (
fields = v.Descriptor().Fields()
fd = getDescriptorByFieldAndName(fields, fieldName)
)
if fd == nil {
switch {
case v.Descriptor().FullName() == structMessageFullname:
fd = fields.ByNumber(structFieldsFieldNumber)
case len(fieldName) > 2 && strings.HasSuffix(fieldName, "[]"):
fd = getDescriptorByFieldAndName(fields, strings.TrimSuffix(fieldName, "[]"))
default:
// If the type is map, you get the string "map[kratos]", where "map" is a field of proto and "kratos" is a key of map
// Use symbol . for separating fields/structs. (eg. structfield.field)View on GitHub (pinned to 668db92c2c)
Solutions
- Send exactly one value for singular fields: use Set instead of Add (Go) or ensure the client form emits a single input
- If multiple values are legitimate, change the proto field to repeated (list) so the IsList branch handles them
- If the duplication comes from merging defaults, deduplicate the key (keep first or last) before encoding the query
- On the server, pre-process r.URL.Query() to drop extra values for known singular keys before calling the form codec
Example fix
// proto: int32 page = 1;
// before: GET /list?page=1&page=2 -> too many values for field "page": 1, 2
// after: GET /list?page=2
// Go client: use Set, not Add
q := url.Values{}
q.Set("page", "2") Defensive patterns
Strategy: validation
Validate before calling
// Ensure singular fields receive exactly one value before binding
func singleValuesOnly(v url.Values, msg protoreflect.Message) error {
for key, vals := range v {
fd := lookupField(msg, key)
if fd == nil {
continue
}
if !fd.IsList() && !fd.IsMap() && len(vals) > 1 {
return fmt.Errorf("field %q accepts one value, got %v", key, vals)
}
}
return nil
} Try / catch
if err := binding.BindQuery(msg, r.URL.Query()); err != nil {
if strings.Contains(err.Error(), "too many values for field") {
return errors.BadRequest("DUPLICATE_PARAM", err.Error())
}
} Prevention
- Use url.Values.Set (Go) for scalar params; reserve Add for repeated proto fields
- Audit frontend serializers that emit arrays for what the proto models as singular
- When demoting repeated->singular in proto, add a temporary server-side check rejecting duplicates with a clear message
- Run contract tests with duplicated keys to confirm the API answers 400, not 500
When it happens
Trigger: A query string or form body repeating a key bound to a scalar field: `?page=1&page=2` when `page` is int32; multiple selected checkbox/radio inputs posted under one name for a non-repeated proto field; url.Values from a proxy that concatenates duplicate params.
Common situations: HTML forms with duplicated input names; query builders appending a default param plus a user-supplied one; client code doing q.Set vs q.Add confusion; field demoted from repeated to singular in the proto while clients still send arrays.
Related errors
- invalid path: %q is not a message
- field already set for oneof %q
- parsing field %q: %w
- parsing list %q: %w
- parsing map key %q: %w
AI-assisted analysis of go-kratos/kratos@668db92c2c (2026-08-16).
Data as JSON: /api/errors/8193ff99c347406a.
Report an issue: GitHub.