go-kratos/kratos · warning
%q is not a valid value
Error message
%q is not a valid value
What it means
Form-binding decoder error for enum fields at proto_decode.go:177: the submitted string did not match any enum value name (enum.Descriptor().Values().ByName returned nil), and the fallback strconv.ParseInt of the string also failed - so the value is neither a known enum value name nor a numeric enum number at all. A correcting nuance: name matching is case-sensitive against the proto value names.
Source
Thrown at encoding/form/proto_decode.go:177
case protoreflect.BoolKind:
v, err := strconv.ParseBool(value)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfBool(v), nil
case protoreflect.EnumKind:
enum, err := protoregistry.GlobalTypes.FindEnumByName(fd.Enum().FullName())
switch {
case errors.Is(err, protoregistry.NotFound):
return protoreflect.Value{}, fmt.Errorf("enum %q is not registered", fd.Enum().FullName())
case err != nil:
return protoreflect.Value{}, fmt.Errorf("failed to look up enum: %w", err)
}
v := enum.Descriptor().Values().ByName(protoreflect.Name(value))
if v == nil {
i, err := strconv.ParseInt(value, 10, 32) //nolint:mnd
if err != nil {
return protoreflect.Value{}, fmt.Errorf("%q is not a valid value", value)
}
v = enum.Descriptor().Values().ByNumber(protoreflect.EnumNumber(i))
if v == nil {
return protoreflect.Value{}, fmt.Errorf("%q is not a valid value", value)
}
}
return protoreflect.ValueOfEnum(v.Number()), nil
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
v, err := strconv.ParseInt(value, 10, 32) //nolint:mnd
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfInt32(int32(v)), nil
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
v, err := strconv.ParseInt(value, 10, 64) //nolint:mnd
if err != nil {
return protoreflect.Value{}, err
}View on GitHub (pinned to 668db92c2c)
Solutions
- Send the exact proto value name (case-sensitive, e.g. ACTIVE) or its integer number (e.g. 1)
- Expose the accepted names via OpenAPI/protobuf docs or a validation endpoint so frontend uses exact tokens
- Add client-side whitelisting of enum values before encoding them into the request
- If users must type friendly labels, map them server-side to proto names before form binding (decode into a string, convert, then set the enum)
Example fix
// enum Status { STATUS_UNSPECIFIED = 0; ACTIVE = 1; INACTIVE = 2; }
// before: GET /x?status=active -> "active" is not a valid value
// after: GET /x?status=ACTIVE (or ?status=1) Defensive patterns
Strategy: validation
Validate before calling
// Whitelist exact enum value names (case-sensitive) before sending
var validStatus = map[string]bool{"ACTIVE": true, "INACTIVE": true}
func okEnum(value string) bool { return validStatus[value] } Type guard
func isValidEnumValue(fd protoreflect.FieldDescriptor, s string) bool {
if fd.Kind() != protoreflect.EnumKind {
return true
}
if fd.Enum().Values().ByName(protoreflect.Name(s)) != nil {
return true
}
n, err := strconv.ParseInt(s, 10, 32)
return err == nil && fd.Enum().Values().ByNumber(protoreflect.EnumNumber(n)) != nil
} Try / catch
if err := binding.BindQuery(msg, q); err != nil {
if strings.Contains(err.Error(), "is not a valid value") {
return errors.BadRequest("BAD_ENUM", err.Error()) // echo the accepted names in your error catalog
}
} Prevention
- Send exact proto value names (UPPER_SNAKE, case-sensitive) or raw numbers
- Generate client enum constants from the proto instead of hand-writing strings
- Publish accepted values per endpoint in docs/OpenAPI and keep them generated
- Map user-facing labels to proto names server-side before binding
When it happens
Trigger: `?status=Active` (wrong case; proto value is ACTIVE), `?status=in_progress` where the proto name is IN_PROGRESS, `?status=y` for a bool-ish enum, or arbitrary strings like `?status=hello` for enum fields. Distinct from error 54: here the string is not even parseable as an integer, so it can only be a bad name.
Common situations: Frontends sending humanized/lowercase labels instead of proto value names; localized status strings; typos after proto renames; enums whose proto names carry a project prefix (STATE_ACTIVE) that clients drop.
Related errors
- invalid path: %q is not a message
- field already set for oneof %q
- too many values for field %q: %s
- parsing field %q: %w
- parsing list %q: %w
AI-assisted analysis of go-kratos/kratos@668db92c2c (2026-08-16).
Data as JSON: /api/errors/6e1ec20cca37860f.
Report an issue: GitHub.