{"record":{"id":"f2e6c3d564c0e3e7","repo":"go-kratos/kratos","slug":"enum-q-is-not-registered","errorCode":null,"errorMessage":"enum %q is not registered","messagePattern":"enum %q is not registered","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"encoding/form/proto_decode.go","lineNumber":169,"sourceCode":"\t\treturn fmt.Errorf(\"parsing map value %q: %w\", fd.FullName().Name(), err)\n\t}\n\tmp.Set(key.MapKey(), value)\n\treturn nil\n}\n\nfunc parseField(fd protoreflect.FieldDescriptor, value string) (protoreflect.Value, error) {\n\tswitch fd.Kind() {\n\tcase protoreflect.BoolKind:\n\t\tv, err := strconv.ParseBool(value)\n\t\tif err != nil {\n\t\t\treturn protoreflect.Value{}, err\n\t\t}\n\t\treturn protoreflect.ValueOfBool(v), nil\n\tcase protoreflect.EnumKind:\n\t\tenum, err := protoregistry.GlobalTypes.FindEnumByName(fd.Enum().FullName())\n\t\tswitch {\n\t\tcase errors.Is(err, protoregistry.NotFound):\n\t\t\treturn protoreflect.Value{}, fmt.Errorf(\"enum %q is not registered\", fd.Enum().FullName())\n\t\tcase err != nil:\n\t\t\treturn protoreflect.Value{}, fmt.Errorf(\"failed to look up enum: %w\", err)\n\t\t}\n\t\tv := enum.Descriptor().Values().ByName(protoreflect.Name(value))\n\t\tif v == nil {\n\t\t\ti, err := strconv.ParseInt(value, 10, 32) //nolint:mnd\n\t\t\tif err != nil {\n\t\t\t\treturn protoreflect.Value{}, fmt.Errorf(\"%q is not a valid value\", value)\n\t\t\t}\n\t\t\tv = enum.Descriptor().Values().ByNumber(protoreflect.EnumNumber(i))\n\t\t\tif v == nil {\n\t\t\t\treturn protoreflect.Value{}, fmt.Errorf(\"%q is not a valid value\", value)\n\t\t\t}\n\t\t}\n\t\treturn protoreflect.ValueOfEnum(v.Number()), nil\n\tcase protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:\n\t\tv, err := strconv.ParseInt(value, 10, 32) //nolint:mnd\n\t\tif err != nil {","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/go-kratos/kratos/blob/668db92c2c001e9552594ba5a8aede8456af6d7e/encoding/form/proto_decode.go#L151-L187","documentation":"Form-binding decoder error for enum-typed fields: protoregistry.GlobalTypes.FindEnumByName(fd.Enum().FullName()) returned protoregistry.NotFound, meaning the enum's Go type is not registered in the binary's global type registry. The decoder needs the registered Go enum (not just the descriptor) to look up value names/numbers, so an unlinked enum type makes every enum value for that field fail with this error.","triggerScenarios":"Binding a form/query with a value for an enum field whose generated Go enum package is not linked into the binary: using protoc-generated descriptors via dynamic messages or reflection without importing the generated enum package; enum types registered under a forked/renamed package so FullName lookup misses; code stripped by dead-code elimination in minimal builds (rare in Go, common after generated files are deleted or moved).","commonSituations":"Mono-repo where the API package with generated enums is only imported by another binary, not this one; switching from static generated types to dynamic descriptors; regenerating protos into a new Go package path and stale registration; shading/renaming packages in CI.","solutions":["Import the generated package containing the enum (even a blank import _ \"your/repo/api/enumpkg\") so its init() registers the type in GlobalTypes","Regenerate protobuf code for the API package and make sure the enum file is compiled into this binary (check go.mod replace directives point at the right tree)","Verify with a tiny test that protoregistry.GlobalTypes.FindEnumByName(\"pkg.EnumName\") succeeds inside the failing binary","If enums come from a third-party proto, ensure that dependency's Go module is a direct import, not merely transitive"],"exampleFix":"// before: enum lookup fails -> enum \"api.Status\" is not registered\nimport _ \"your/repo/api/types\" // missing in this binary\n\n// after: ensure the generated enum package is imported where binding happens\nimport _ \"your/repo/api/types\" // registers api.Status via init()","handlingStrategy":"validation","validationCode":"// Startup check: all enums referenced by the request types must be registered\nfunc enumsRegistered(msgs ...protoreflect.Message) error {\n\tfor _, m := range msgs {\n\t\tvar err error\n\t\tm.Descriptor().Fields().Range(func(fd protoreflect.FieldDescriptor) bool {\n\t\t\tif fd.Kind() == protoreflect.EnumKind {\n\t\t\t\t_, e := protoregistry.GlobalTypes.FindEnumByName(fd.Enum().FullName())\n\t\t\t\tif e != nil {\n\t\t\t\terr = fmt.Errorf(\"enum %q: %w\", fd.Enum().FullName(), e)\n\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":"func enumRegistered(fullName protoreflect.FullName) bool {\n\t_, err := protoregistry.GlobalTypes.FindEnumByName(fullName)\n\treturn !errors.Is(err, protoregistry.NotFound)\n}","tryCatchPattern":"if err := binding.BindQuery(msg, q); err != nil {\n\tif strings.Contains(err.Error(), \"is not registered\") {\n\t\t// build/link problem, not user input: fail loudly, no retry\n\t\tlog.Error(\"enum type missing from binary\", \"err\", err)\n\t\treturn errors.InternalServer(\"ENUM_NOT_LINKED\", err.Error())\n\t}\n}","preventionTips":["Blank-import the generated enum packages in the binary that performs form binding","Add a unit test asserting FindEnumByName succeeds for every enum your API uses","Keep generated code and the binary in one module graph; beware go.mod replace forks","Fail fast at process start (registration smoke test) instead of at first request"],"tags":["go","kratos","form-binding","protobuf","enum","protoregistry"],"backgroundTag":null,"analyzedSha":"668db92c2c001e9552594ba5a8aede8456af6d7e","analyzedAt":"2026-08-16T02:07:20.704Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}