{"record":{"id":"ac051e6bf693c086","repo":"apache/beam","slug":"registercoder-failed-for-type-v","errorCode":null,"errorMessage":"RegisterCoder failed for type %v","messagePattern":"RegisterCoder failed for type (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"sdks/go/pkg/beam/core/graph/coder/registry.go","lineNumber":49,"sourceCode":"// RegisterCoder registers a user defined coder for a given type, and will\n// be used if there is no beam coder for that type. Must be called prior to beam.Init(),\n// preferably in an init() function.\n//\n// Coders are encoder and decoder pairs, and operate around []bytes.\n//\n// The coder used for a given type follows this ordering:\n//  1. Coders for Known Beam types.\n//  2. Coders registered for specific types\n//  3. Coders registered for interfaces types\n//  4. Default coder (JSON)\n//\n// Types of kind Interface, are handled specially by the registry, so they may be iterated\n// over to check if element types implement them.\n//\n// Repeated registrations of the same type overrides prior ones.\nfunc RegisterCoder(t reflect.Type, enc, dec any) {\n\tif _, err := NewCustomCoder(t.String(), t, enc, dec); err != nil {\n\t\tpanic(errors.Wrapf(err, \"RegisterCoder failed for type %v\", t))\n\t}\n\n\tif t.Kind() == reflect.Interface {\n\t\t// If it's already in the registry, then it's already in the list\n\t\t// and should be removed.\n\t\tif _, ok := coderRegistry[t]; ok {\n\t\t\tvar index int\n\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}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/coder/registry.go#L31-L67","documentation":"RegisterCoder validates the encoder/decoder pair by constructing a CustomCoder and panics wrapping the error as \"RegisterCoder failed for type %v\" if construction fails. Because registration typically happens in init(), this panic crashes the program at startup. It means the supplied enc/dec functions do not satisfy the validators' signature requirements for the type.","triggerScenarios":"Calling coder.RegisterCoder(t, enc, dec) with enc/dec whose signatures fail validateEncoder/validateDecoder — wrong parameter or return types, non-function values, or wrong arity.","commonSituations":"Registration in package init() with hand-written funcs whose types drifted after a refactor; copying a registration for a different type without updating the signatures; passing methods instead of matching plain funcs.","solutions":["Make encode have signature func(T) []byte and decode func([]byte) T exactly matching t","Test the registration early (a unit test or build-time check) since it panics in init","Read the wrapped underlying error to see which validation failed","Check for validator/signature changes after Beam upgrades"],"exampleFix":"// before\ncoder.RegisterCoder(reflect.TypeOf(MyType{}), func(m MyType) ([]byte, error) { ... }, ...)\n// after\ncoder.RegisterCoder(reflect.TypeOf(MyType{}),\n    func(m MyType) []byte { return encodeMyType(m) },\n    func(b []byte) MyType { return decodeMyType(b) })","handlingStrategy":"validation","validationCode":"enc := func(v T) []byte { return encodeT(v) }\ndec := func(b []byte) T { return decodeT(b) }\nif _, err := coder.NewCustomCoder(\"check\", reflect.TypeOf(T{}), enc, dec); err != nil {\n    panic(fmt.Sprintf(\"invalid coder funcs for T: %v\", err))\n}","typeGuard":"func validCoderFuncs(t reflect.Type, enc, dec any) bool {\n    _, err := coder.NewCustomCoder(\"check\", t, enc, dec)\n    return err == nil\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"coder registration failed at startup: %v\", r)\n    }\n}()","preventionTips":["Register coders with exact func(T) []byte / func([]byte) T signatures","Smoke-test init() registrations in CI before deployment","Re-check registrations after any type refactor or Beam upgrade"],"tags":["go","beam","panic","coder-registry"],"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-20T03:17:13.778Z"}