{"record":{"id":"1d72d503c149cfd1","repo":"apache/beam","slug":"type-already-registered-for-v-and-new-type-v-v-existing-type","errorCode":null,"errorMessage":"type already registered for %v, and new type %v != %v (existing type)","messagePattern":"type already registered for (.+?), and new type (.+?) != (.+?) \\(existing type\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"sdks/go/pkg/beam/core/runtime/types.go","lineNumber":43,"sourceCode":"var types = make(map[string]reflect.Type)\n\n// RegisterType inserts \"external\" types into a global type registry to bypass\n// serialization and preserve full method information. It should be called in\n// init() only. Returns the external key for the type.\nfunc RegisterType(t reflect.Type) string {\n\tif initialized {\n\t\tpanic(\"Init hooks have already run. Register type during init() instead.\")\n\t}\n\n\tt = reflectx.SkipPtr(t)\n\n\tk, ok := TypeKey(t)\n\tif !ok {\n\t\tpanic(fmt.Sprintf(\"invalid registration type: %v\", t))\n\t}\n\n\tif v, exists := types[k]; exists && v != t {\n\t\tpanic(fmt.Sprintf(\"type already registered for %v, and new type %v != %v (existing type)\", k, t, v))\n\t}\n\ttypes[k] = t\n\treturn k\n}\n\n// LookupType looks up a type in the global type registry by external key.\nfunc LookupType(key string) (reflect.Type, bool) {\n\tt, ok := types[key]\n\treturn t, ok\n}\n\n// TypeKey returns the external key of a given type. Returns false if not a\n// candidate for registration.\nfunc TypeKey(t reflect.Type) (string, bool) {\n\tif t.PkgPath() == \"\" || t.Name() == \"\" {\n\t\treturn \"\", false // no pre-declared or unnamed types\n\t}\n\treturn fmt.Sprintf(\"%v.%v\", t.PkgPath(), t.Name()), true","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/types.go#L25-L61","documentation":"This panic fires in RegisterType when two different Go types map to the same TypeKey. The Apache Beam Go SDK keeps a global registry mapping string type keys to reflect.Type values; if a key computed for a new type is already present but bound to a different type, the registry would be corrupted, so the SDK panics. It signals a genuine type-identity collision, not a user-facing error return.","triggerScenarios":"Calling beam.RegisterType (directly or via RegisterDoFn/RegisterCoder) with a type whose TypeKey (type name incl. package path, plus generic type arguments) collides with an already-registered but distinct type; e.g. registering two different types that produce the same key, or registering a type in a package that gets re-loaded under an identical key.","commonSituations":"Duplicate registrations across packages with identical type names in different vendored copies; custom TypeKey/Encoders registered twice with differing types; build-tag or plugin setups that load the same package twice under one binary; renaming a struct while stale generated init code still registers the old one.","solutions":["Check which two types collide: the panic message shows the key, the new type, and the existing type; align the registrations so only one type is registered per key.","Remove duplicate beam.RegisterType / RegisterDoFn / RegisterCoder calls for the colliding type (often in init functions of copied or vendored packages).","If a custom type key is being generated, make it unique (include the full package path and any generic parameters).","Restructure code so distinct types are not name-identical across vendor copies; consolidate duplicated package copies."],"exampleFix":"// before\n// package a: type Event struct{}\n// package b (vendored copy): type Event struct{}\nbeam.RegisterType(reflect.TypeOf(a.Event{}))\nbeam.RegisterType(reflect.TypeOf(b.Event{})) // panics: same key, different type\n// after\n// keep a single canonical definition of Event and register it once\nbeam.RegisterType(reflect.TypeOf(a.Event{}))","handlingStrategy":"validation","validationCode":"k := beam.TypeKey(reflect.TypeOf(myType{}))\nif _, exists := registryCheck(k); exists { /* skip duplicate registration or ensure identical type */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register each type exactly once, ideally in the package that defines it via init().","Avoid vendoring duplicate copies of packages that call beam.RegisterType.","Make custom type keys include the full package path and generic parameters."],"tags":["go","type-registry","duplicate-registration","panic"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}