grpc/grpc-go · critical
cannot register a nil Codec
Error message
cannot register a nil Codec
What it means
encoding.RegisterCodec (encoding.go:132) registers a Codec for a content-subtype so gRPC can marshal/unmarshal messages. It panics if passed a nil Codec interface because storing nil would later produce nil-pointer dereferences deep in the codec lookup path; failing fast at registration is safer. Must be called from init() (not thread-safe).
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 03255a9237)
Solutions
- Find the RegisterCodec call in the panic trace and ensure the codec value is non-nil and fully constructed.
- Register codecs in an init() block and verify the package is imported (blank import if needed) so the variable is initialized.
- Add a guard: if codec != nil { encoding.RegisterCodec(codec) } if the codec is optional.
Example fix
// before
var myCodec encoding.Codec // nil, never assigned
func init() { encoding.RegisterCodec(myCodec) } // panics
// after
func init() {
c := &jsonpb.Codec{}
encoding.RegisterCodec(c)
} Defensive patterns
Strategy: validation
Validate before calling
// Guard nil before registering at init time
func init() {
c := buildCodec()
if c == nil {
log.Fatal("codec is nil; check build tags / imports")
}
encoding.RegisterCodec(c)
} Type guard
func isCodecNil(c encoding.Codec) bool { return c == nil } Prevention
- Always construct the codec value explicitly; avoid package-level nil variables passed to RegisterCodec.
- Blank-import the package that defines the codec so its init() runs.
- Unit-test that RegisterCodec is reached with a populated value.
When it happens
Trigger: Calling encoding.RegisterCodec(nil), most often because a variable holding the codec was never initialized, a build tag left the codec nil, or a constructor returned nil and was passed directly.
Common situations: A custom codec struct's package was not imported (so the variable is nil); a codec depending on a build tag (e.g. a GPU/protobuf variant) that wasn't selected; a refactor that replaced the codec value with nil.
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()
- grpc: invalid gzip compression level: %d
- proto: failed to marshal, message is %T, want proto.Message
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/6721d487ea7a82bc.
Report an issue: GitHub.