{"record":{"id":"ba147ffa7cc70a1d","repo":"grpc/grpc-go","slug":"cannot-register-a-nil-codecv2","errorCode":null,"errorMessage":"cannot register a nil CodecV2","messagePattern":"cannot register a nil CodecV2","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"encoding/encoding_v2.go","lineNumber":65,"sourceCode":"// servers.\n//\n// The CodecV2 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 CodecV2.  This\n// is case-insensitive, and is stored and looked up as lowercase.  If the\n// result of calling Name() is an empty string, RegisterCodecV2 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// If both a Codec and CodecV2 are registered with the same name, the CodecV2\n// will be used.\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 RegisterCodecV2(codec CodecV2) {\n\tif codec == nil {\n\t\tpanic(\"cannot register a nil CodecV2\")\n\t}\n\tif codec.Name() == \"\" {\n\t\tpanic(\"cannot register CodecV2 with empty string result for Name()\")\n\t}\n\tcontentSubtype := strings.ToLower(codec.Name())\n\tregisteredCodecs[contentSubtype] = codec\n}\n\n// GetCodecV2 gets a registered CodecV2 by content-subtype, or nil if no CodecV2 is\n// registered for the content-subtype.\n//\n// The content-subtype is expected to be lowercase.\nfunc GetCodecV2(contentSubtype string) CodecV2 {\n\tc, _ := registeredCodecs[contentSubtype].(CodecV2)\n\treturn c\n}\n","sourceCodeStart":47,"sourceCodeEnd":82,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/encoding/encoding_v2.go#L47-L82","documentation":"encoding.RegisterCodecV2 (encoding_v2.go:63) registers a CodecV2 (the newer buffer-pool-aware codec interface). Like RegisterCodec it panics on a nil value to avoid later nil-dereferences. CodecV2 takes precedence over Codec when both share a name. Must be called from init().","triggerScenarios":"Calling encoding.RegisterCodecV2(nil) because the CodecV2 value was never assigned or a constructor returned nil.","commonSituations":"Upgrading a codec to the V2 interface but the package variable holding it is still nil; a build-tag-gated codec whose tag wasn't enabled; a refactor that removed the assignment.","solutions":["Locate the RegisterCodecV2 call and ensure the value is a fully-constructed non-nil CodecV2.","Keep registration inside init() and confirm the defining package is imported.","Guard optional registration: if c != nil { encoding.RegisterCodecV2(c) }."],"exampleFix":"// before\nvar c2 encoding.CodecV2 // nil\nfunc init() { encoding.RegisterCodecV2(c2) } // panics\n\n// after\nfunc init() { encoding.RegisterCodecV2(&protobuf.NewCodec()) }","handlingStrategy":"validation","validationCode":"func init() {\n    c := buildCodecV2()\n    if c == nil {\n        log.Fatal(\"codecv2 is nil\")\n    }\n    encoding.RegisterCodecV2(c)\n}","typeGuard":"func isCodecV2Nil(c encoding.CodecV2) bool { return c == nil }","tryCatchPattern":null,"preventionTips":["Construct CodecV2 explicitly; never register an uninitialized package-level variable.","Confirm the defining package is imported so init() runs.","Guard optional registration with a nil check."],"tags":["encoding","codec","codecv2","panic","grpc-go","init"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}