go-kratos/kratos · error
invalid formatting for map key
Error message
invalid formatting for map key
What it means
errInvalidFormatMapKey (encoding/form/proto_decode.go:25) is returned by parseURLQueryMapKey via populateMapField when the URL query key addressing a proto map field cannot be split into (field, key). Accepted forms are 'field[key]=value' (brackets wrapping the whole tail: startIndex>0, endIndex after it, nothing beyond ']') or exactly one separator as in 'field.key=value'. Everything else - no bracket and dot-count != 1, empty field part, bracket at position 0, '[' after ']', trailing characters after ']', unmatched/multiple brackets - fails.
Source
Thrown at encoding/form/proto_decode.go:25
"net/url"
"strconv"
"strings"
"time"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/fieldmaskpb"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
const fieldSeparator = "."
var errInvalidFormatMapKey = errors.New("invalid formatting for map key")
// DecodeValues decode url value into proto message.
func DecodeValues(msg proto.Message, values url.Values) error {
for key, values := range values {
if err := populateFieldValues(msg.ProtoReflect(), strings.Split(key, "."), values); err != nil {
return err
}
}
return nil
}
func populateFieldValues(v protoreflect.Message, fieldPath []string, values []string) error {
if len(fieldPath) < 1 {
return errors.New("no field path")
}
if len(values) < 1 {
return errors.New("no value provided")
}View on GitHub (pinned to 668db92c2c)
Solutions
- Use the canonical bracket form for map fields: 'mymap[key]=value'
- Or the single-dot form with exactly one dot: 'mymap.key=value'
- Avoid mixing nested message dots and bracket keys in one key; for a map inside a message use 'msg.field[key]=value' so fieldPath length 2 hits the map branch
- Sanitize/validate incoming query keys before DecodeValues when keys come from untrusted clients
Example fix
// before
values := url.Values{}
values.Set("labels.meta.app", "kratos") // two dots, no brackets -> invalid
form.DecodeValues(msg, values)
// after
values := url.Values{}
values.Set("labels[meta.app]", "kratos") // field[key]
// or exactly one dot:
values.Set("labels.meta", "kratos") Defensive patterns
Strategy: validation
Validate before calling
var mapKeyRe = regexp.MustCompile(`^[^\[\].]+(\[[^\[\]]*\])?$`)
func validQueryKeys(q url.Values) error {
for k := range q {
if !mapKeyRe.MatchString(k) && strings.Count(k, ".") > 1 {
return fmt.Errorf("suspicious map key %q", k)
}
}
return nil
} Prevention
- Emit map fields as 'field[key]=value' or exactly 'field.key=value' - never both notations in one key
- Encode brackets properly when clients build query strings programmatically
- Add contract tests that bind representative query strings to proto fixtures covering map fields
When it happens
Trigger: Form/query binding a proto message with a map field where the query contains keys like 'map[]', 'map[', 'kratos]', '[[]', 'map.kratos.v2' (two dots, no brackets), '.kratos' (empty field), or 'map[kratos]=' style malformed tails. The map branch is entered when the field descriptor is a map and fieldPath length is 2 (line 51) or on the post-subfield path (line 58), then strings.Join(fieldPath, ".") is re-parsed by parseURLQueryMapKey.
Common situations: Hand-built query strings from templates or clients that URL-encode brackets wrongly; using both dot nesting and bracket keys in the same key ('a.b[c]'); nested message paths whose second element is the map key written with extra dots; migrating from go-playground/form style keys with subtle syntax drift (the code comments reference that format).
Related errors
AI-assisted analysis of go-kratos/kratos@668db92c2c (2026-08-16).
Data as JSON: /api/errors/c248cc1f017fa072.
Report an issue: GitHub.