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

  1. Send exactly one value for singular fields: use Set instead of Add (Go) or ensure the client form emits a single input
  2. If multiple values are legitimate, change the proto field to repeated (list) so the IsList branch handles them
  3. If the duplication comes from merging defaults, deduplicate the key (keep first or last) before encoding the query
  4. 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

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


AI-assisted analysis of go-kratos/kratos@668db92c2c (2026-08-16). Data as JSON: /api/errors/8193ff99c347406a. Report an issue: GitHub.