grpc/grpc-go · critical
cannot register a nil Codec
Error message
cannot register a nil Codec
What it means
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.
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.
Example fix
// before
var myCodec encoding.Codec
func init() { encoding.RegisterCodec(myCodec) } // panic: nil
// after
type jsonCodec struct{}
func (jsonCodec) Name() string { return "json" }
func (jsonCodec) Marshal(v any) ([]byte, error) { /* ... */ return nil, nil }
func (jsonCodec) Unmarshal(d []byte, v any) error { /* ... */ return nil }
func init() { encoding.RegisterCodec(jsonCodec{}) } Defensive patterns
Strategy: validation
Validate before calling
// Guard before registering a Codec.
func registerSafe(c encoding.Codec) {
if c == nil {
log.Print("skipping registration: nil codec")
return
}
encoding.RegisterCodec(c)
} Try / catch
// Panics are fatal by design; recover only in test/setup shims.
defer func() {
if r := recover(); r != nil {
log.Fatalf("codec registration failed: %v", r)
}
}()
encoding.RegisterCodec(c) Prevention
- 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.
When it happens
Trigger: 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)`).
Common situations: 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.
Related errors
- cannot register Codec with empty string result for Name()
- cannot register a nil CodecV2
- cannot register CodecV2 with empty string result for Name()
- cannot use component logger as grpclog logger
- Cannot free freed buffer
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/6721d487ea7a82bc.
Report an issue: GitHub.
Appendix: source
Thrown at encoding/encoding.go:134
var registeredCodecs = make(map[string]any)
// RegisterCodec registers the provided Codec for use with all gRPC clients and
// servers.
//
// The Codec will be stored and looked up by result of its Name() method, which
// should match the content-subtype of the encoding handled by the Codec. This
// is case-insensitive, and is stored and looked up as lowercase. If the
// result of calling Name() is an empty string, RegisterCodec will panic. See
// Content-Type on
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
// more details.
//
// NOTE: this function must only be called during initialization time (i.e. in
// an init() function), and is not thread-safe. If multiple Codecs are
// registered with the same name, the one registered last will take effect.
func RegisterCodec(codec Codec) {
if codec == nil {
panic("cannot register a nil Codec")
}
if codec.Name() == "" {
panic("cannot register Codec with empty string result for Name()")
}
contentSubtype := strings.ToLower(codec.Name())
registeredCodecs[contentSubtype] = codec
}
// GetCodec gets a registered Codec by content-subtype, or nil if no Codec is
// registered for the content-subtype.
//
// The content-subtype is expected to be lowercase.
func GetCodec(contentSubtype string) Codec {
c, _ := registeredCodecs[contentSubtype].(Codec)
return c
}
View on GitHub (pinned to 0c51461d27)