{"record":{"id":"2b42c0d9a88eb354","repo":"go-kratos/kratos","slug":"failed-to-look-up-enum-w","errorCode":null,"errorMessage":"failed to look up enum: %w","messagePattern":"failed to look up enum: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"encoding/form/proto_decode.go","lineNumber":171,"sourceCode":"\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 {\n\t\t\treturn protoreflect.Value{}, err\n\t\t}","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/go-kratos/kratos/blob/668db92c2c001e9552594ba5a8aede8456af6d7e/encoding/form/proto_decode.go#L153-L189","documentation":"Form-binding decoder error for enum fields where the global registry lookup failed with an error other than protoregistry.NotFound - FindEnumByName returned a real error. In practice this is the protoregistry conflict path (e.g. protoregistry.DuplicateRegistration) or a registry-in-an-inconsistent-state failure, wrapped verbatim with %w so the original error text is visible.","triggerScenarios":"Two different Go packages registering an enum with the same full name in GlobalTypes - typically the same proto generated twice into different Go packages and both linked into one binary (vendored fork + original, or api package copied between module paths); or a custom registry injected with conflicting entries. The switch at proto_decode.go:170-172 separates NotFound (error 51) from these other failures.","commonSituations":"Forking an api/proto repo and importing both fork and upstream in the same service; go.mod replace pointing at a copy while a transitive dependency still pulls the original; generated code duplicated across major versions of an API module; CI builds that vendor two generations of the same proto.","solutions":["Read the wrapped error - DuplicateRegistration names the conflicting full name; then audit go.mod (go mod graph / go list -m all) for two sources of the same generated package","Remove or rename one of the conflicting generated packages (keep either the fork or the upstream, not both) and use go.mod replace to unify on a single copy","Regenerate protos with consistent go_package options so full names map to one Go package","Add a startup smoke test that calls protoregistry.GlobalTypes.FindEnumByName for your enums to catch conflicts before traffic"],"exampleFix":"# before: both linked -> failed to look up enum: duplicate registration .../Status\ngo.mod:\n  require github.com/org/api v1.2.3\n  replace github.com/org/api => ./forks/api-copy\n\n# after: single source of the generated enums\n  require github.com/org/api v1.2.3   # no replace to a duplicate copy","handlingStrategy":"validation","validationCode":"// Detect duplicate enum registration early in a test\nfunc TestNoEnumConflicts(t *testing.T) {\n\tprotoregistry.GlobalTypes.RangeEnumsByMessage(func(protoreflect.EnumType) bool { return true })\n\t// plus: register a second copy in a fork and expect DuplicateRegistration\n}","typeGuard":null,"tryCatchPattern":"if err := binding.BindQuery(msg, q); err != nil {\n\tif strings.Contains(err.Error(), \"failed to look up enum\") {\n\t\tlog.Error(\"protoregistry conflict or failure\", \"err\", err) // wrapped cause names the duplicate\n\t\treturn errors.InternalServer(\"ENUM_REGISTRY\", err.Error())\n\t}\n}","preventionTips":["Never link two copies of the same generated proto package (fork + upstream) in one binary","Unify generated code paths with a single go.mod replace during migrations","Check go list -m all for duplicate module paths providing identical proto packages in CI","Run the enum registration smoke test in every build environment"],"tags":["go","kratos","form-binding","protobuf","enum","protoregistry","dependency-conflict"],"backgroundTag":null,"analyzedSha":"668db92c2c001e9552594ba5a8aede8456af6d7e","analyzedAt":"2026-08-16T02:07:20.704Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}