{"record":{"id":"1b937e7574d6d6b4","repo":"apache/beam","slug":"creating-v-customcoder-for-type-v-failed","errorCode":null,"errorMessage":"Creating %v CustomCoder for type %v failed","messagePattern":"Creating (.+?) CustomCoder for type (.+?) failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"sdks/go/pkg/beam/core/graph/coder/registry.go","lineNumber":75,"sourceCode":"\t\t\tfor i, iT := range interfaceOrdering {\n\t\t\t\tif iT == t {\n\t\t\t\t\tindex = i\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tinterfaceOrdering = append(interfaceOrdering[:index], interfaceOrdering[index+1:]...)\n\t\t}\n\t\t// Either way, always append.\n\t\tinterfaceOrdering = append(interfaceOrdering, t)\n\t}\n\tname := t.String() // Use the real type names for coders.\n\tcoderRegistry[t] = func(rt reflect.Type) *CustomCoder {\n\t\t// We need to provide the concrete type, so that coders that use\n\t\t// the reflect.Type have the proper instance.\n\t\tcc, err := NewCustomCoder(name, rt, enc, dec)\n\t\tif err != nil {\n\t\t\t// An error on look up shouldn't happen after the validation.\n\t\t\tpanic(errors.Wrapf(err, \"Creating %v CustomCoder for type %v failed\", name, rt))\n\t\t}\n\t\treturn cc\n\t}\n}\n\n// RegisterDeterministicCoderWithFuncs is like RegisterDeterministicCoder\n// but accepts pre-wrapped reflectx.Func values (typically built via\n// reflectx.MakeFuncWithName) so the caller controls the function name\n// used during cross-worker serialization. This is required for\n// closures inside Go generic functions where different type\n// instantiations produce closures with the same compiler name.\nfunc RegisterDeterministicCoderWithFuncs(t reflect.Type, encFn, decFn *funcx.Fn) {\n\tname := t.String()\n\tcoderRegistry[t] = func(rt reflect.Type) *CustomCoder {\n\t\treturn NewCustomCoderWithFuncs(name, rt, encFn, decFn)\n\t}\n\tdeterministicRegistry[t] = true\n}","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/coder/registry.go#L57-L93","documentation":"Inside the registry's lazy per-type factory, NewCustomCoder is re-invoked with the concrete type rt; if it fails the code panics with \"Creating %v CustomCoder for type %v failed\". The source comment notes this should be unreachable after Register-time validation, so it signals an internal invariant violation — usually the concrete type rt differs from the registered type in a way validation did not anticipate.","triggerScenarios":"Looking up a coder by concrete type rt where re-creating the CustomCoder with rt fails despite passing validation at registration time.","commonSituations":"Registering for a base/interface type then looking up with a related concrete type where the encode/decode funcs no longer type-check; Beam-internal bugs after version upgrades.","solutions":["Register the coder for the exact concrete type being looked up","Treat as a Beam bug: verify the reproduction and file/check an issue","Verify no duplicate registrations with mismatched funcs for related types"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if strings.Contains(fmt.Sprint(r), \"CustomCoder for type\") {\n            log.Fatalf(\"registry invariant violated: %v\", r)\n        }\n        panic(r)\n    }\n}()","preventionTips":["Register coders for the exact concrete type that will be looked up","Avoid duplicate/conflicting registrations for related types","Report reproducible hits to Beam — this path is expected unreachable"],"tags":["go","beam","panic","coder-registry","invariant"],"backgroundTag":"internal-invariant-violation","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"}