{"record":{"id":"e69d384c8d93b812","repo":"apache/beam","slug":"logical-types-may-not-be-registered-with-empty-interface","errorCode":null,"errorMessage":"Logical Types may not be registered with empty interface types. %v has no methods.","messagePattern":"Logical Types may not be registered with empty interface types\\. (.+?) has no methods\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/runtime/graphx/schema/logicaltypes.go","lineNumber":112,"sourceCode":"\t_, err := r.reflectTypeToFieldType(st)\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"LogicalType[%v] has an invalid StorageType %v: %v\", lt.ID(), st, err))\n\t}\n\tif len(lt.ID()) == 0 {\n\t\tpanic(fmt.Sprintf(\"invalid logical type, bad id: %v -> %v\", lt.GoType(), lt.StorageType()))\n\t}\n\t// TODO add duplication checks.\n\tr.logicalTypeIdentifiers[lt.GoType()] = lt.ID()\n\tr.logicalTypes[lt.ID()] = lt\n}\n\n// RegisterLogicalTypeProvider allows registration of providers for interface types.\nfunc (r *Registry) RegisterLogicalTypeProvider(rt reflect.Type, ltp LogicalTypeProvider) {\n\tif rt.Kind() != reflect.Interface {\n\t\tpanic(fmt.Sprintf(\"Logical Types must be registered with interface types. %v is not an interface type.\", rt))\n\t}\n\tif rt.NumMethod() == 0 {\n\t\tpanic(fmt.Sprintf(\"Logical Types may not be registered with empty interface types. %v has no methods.\", rt))\n\t}\n\tr.logicalTypeProviders[rt] = ltp\n\tr.logicalTypeInterfaces = append(r.logicalTypeInterfaces, rt)\n}\n\n// LogicalType is a mapping between custom Go types, and their schema equivalent storage types.\n//\n// A LogicalType is a way to define a type that can be stored in a schema field\n// using a known underlying type for storage. The storage type must be comprised of\n// known schema field types, or pre-registered LogicalTypes.\n//\n// LogicalTypes may not be mutually recursive at any level of indirection.\n// LogicalTypes must map from a Go type to a single Schema Equivalent storage type.\ntype LogicalType struct {\n\tidentifier          string\n\tgoT, storageT, argT reflect.Type\n\targV                reflect.Value\n}","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/graphx/schema/logicaltypes.go#L94-L130","documentation":"A logical type provider registered on an interface with zero methods would match every Go value, since all types satisfy the empty interface. To prevent this pathological catch-all registration, the library panics when rt.NumMethod() == 0.","triggerScenarios":"Calling RegisterLogicalTypeProvider with an interface type that declares no methods, e.g. reflect.TypeOf((*interface{})(nil)).Elem() or a marker interface without methods.","commonSituations":"Using interface{} or empty marker interfaces to register a provider; designing a tagged interface where methods were removed during refactoring.","solutions":["Give the interface at least one method that your values implement","Register concrete types via RegisterLogicalType instead of an empty-interface provider","Add a marker method to the interface to narrow matching"],"exampleFix":"// before\ntype MyTag interface{}\n// after\ntype MyTag interface{ IsMyType() }","handlingStrategy":"validation","validationCode":"if rt.Kind() == reflect.Interface && rt.NumMethod() == 0 {\n    return errors.New(\"provider interface must declare at least one method\")\n}","typeGuard":"func isNonEmptyInterface(rt reflect.Type) bool { return rt != nil && rt.Kind() == reflect.Interface && rt.NumMethod() > 0 }","tryCatchPattern":"defer func() { if r := recover(); r != nil { err = fmt.Errorf(\"register provider: %v\", r) } }()","preventionTips":["Give marker interfaces at least one method","Never register providers on interface{}","Review interface design before registration"],"tags":["go","apache-beam","schema","reflection","panic"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}