go-kratos/kratos · error

failed to look up enum: %w

Error message

failed to look up enum: %w

What it means

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.

Source

Thrown at encoding/form/proto_decode.go:171

	mp.Set(key.MapKey(), value)
	return nil
}

func parseField(fd protoreflect.FieldDescriptor, value string) (protoreflect.Value, error) {
	switch fd.Kind() {
	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
		}

View on GitHub (pinned to 668db92c2c)

Solutions

  1. 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
  2. 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
  3. Regenerate protos with consistent go_package options so full names map to one Go package
  4. Add a startup smoke test that calls protoregistry.GlobalTypes.FindEnumByName for your enums to catch conflicts before traffic

Example fix

# before: both linked -> failed to look up enum: duplicate registration .../Status
go.mod:
  require github.com/org/api v1.2.3
  replace github.com/org/api => ./forks/api-copy

# after: single source of the generated enums
  require github.com/org/api v1.2.3   # no replace to a duplicate copy
Defensive patterns

Strategy: validation

Validate before calling

// Detect duplicate enum registration early in a test
func TestNoEnumConflicts(t *testing.T) {
	protoregistry.GlobalTypes.RangeEnumsByMessage(func(protoreflect.EnumType) bool { return true })
	// plus: register a second copy in a fork and expect DuplicateRegistration
}

Try / catch

if err := binding.BindQuery(msg, q); err != nil {
	if strings.Contains(err.Error(), "failed to look up enum") {
		log.Error("protoregistry conflict or failure", "err", err) // wrapped cause names the duplicate
		return errors.InternalServer("ENUM_REGISTRY", err.Error())
	}
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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