{"record":{"id":"6721d487ea7a82bc","repo":"grpc/grpc-go","slug":"cannot-register-a-nil-codec","errorCode":null,"errorMessage":"cannot register a nil Codec","messagePattern":"cannot register a nil Codec","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"encoding/encoding.go","lineNumber":134,"sourceCode":"var registeredCodecs = make(map[string]any)\n\n// RegisterCodec registers the provided Codec for use with all gRPC clients and\n// servers.\n//\n// The Codec will be stored and looked up by result of its Name() method, which\n// should match the content-subtype of the encoding handled by the Codec.  This\n// is case-insensitive, and is stored and looked up as lowercase.  If the\n// result of calling Name() is an empty string, RegisterCodec will panic. See\n// Content-Type on\n// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for\n// more details.\n//\n// NOTE: this function must only be called during initialization time (i.e. in\n// an init() function), and is not thread-safe.  If multiple Codecs are\n// registered with the same name, the one registered last will take effect.\nfunc RegisterCodec(codec Codec) {\n\tif codec == nil {\n\t\tpanic(\"cannot register a nil Codec\")\n\t}\n\tif codec.Name() == \"\" {\n\t\tpanic(\"cannot register Codec with empty string result for Name()\")\n\t}\n\tcontentSubtype := strings.ToLower(codec.Name())\n\tregisteredCodecs[contentSubtype] = codec\n}\n\n// GetCodec gets a registered Codec by content-subtype, or nil if no Codec is\n// registered for the content-subtype.\n//\n// The content-subtype is expected to be lowercase.\nfunc GetCodec(contentSubtype string) Codec {\n\tc, _ := registeredCodecs[contentSubtype].(Codec)\n\treturn c\n}\n","sourceCodeStart":116,"sourceCodeEnd":151,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/encoding/encoding.go#L116-L151","documentation":"encoding.RegisterCodec (encoding/encoding.go:132) registers a custom message Codec in gRPC's global registry, keyed by its Name(). It panics with this message at line 133-135 when codec == nil, because a nil codec would later cause nil-pointer dereferences inside Marshal/Unmarshal on every RPC. gRPC fails fast at registration (init) time instead of at RPC time.","triggerScenarios":"Calling encoding.RegisterCodec(nil) directly; registering a package-level `var c encoding.Codec` that was never assigned; passing the nil result of a constructor whose error the caller ignored (e.g. `c, _ := NewCodec(cfg); RegisterCodec(c)`).","commonSituations":"Writing a custom JSON/flatbuffers/avro codec and forgetting to instantiate it; conditional registration behind a build tag where the codec is only created in one path; a refactor leaving a dangling nil reference before the init() that registers it.","solutions":["Construct the codec value before calling RegisterCodec so it is never nil.","If your codec constructor can return an error, check it and skip registration (or log.Fatal) on failure instead of passing the nil result.","Register in an init() block so initialization order is deterministic and the nil is obvious at startup."],"exampleFix":"// before\nvar myCodec encoding.Codec\nfunc init() { encoding.RegisterCodec(myCodec) } // panic: nil\n\n// after\ntype jsonCodec struct{}\nfunc (jsonCodec) Name() string                  { return \"json\" }\nfunc (jsonCodec) Marshal(v any) ([]byte, error)  { /* ... */ return nil, nil }\nfunc (jsonCodec) Unmarshal(d []byte, v any) error { /* ... */ return nil }\nfunc init() { encoding.RegisterCodec(jsonCodec{}) }","handlingStrategy":"validation","validationCode":"// Guard before registering a Codec.\nfunc registerSafe(c encoding.Codec) {\n    if c == nil {\n        log.Print(\"skipping registration: nil codec\")\n        return\n    }\n    encoding.RegisterCodec(c)\n}","typeGuard":null,"tryCatchPattern":"// Panics are fatal by design; recover only in test/setup shims.\ndefer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"codec registration failed: %v\", r)\n    }\n}()\nencoding.RegisterCodec(c)","preventionTips":["Construct the codec value immediately before the RegisterCodec call in the same init().","Treat any codec constructor error as fatal before registering, never pass its nil result.","Add a unit test that exercises registration so a nil surfaces in CI, not in production."],"tags":["encoding","codec","registration","panic","go"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}