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

  1. Find the RegisterCodec call in the panic trace and ensure the codec value is non-nil and fully constructed.
  2. Register codecs in an init() block and verify the package is imported (blank import if needed) so the variable is initialized.
  3. 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

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


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/6721d487ea7a82bc. Report an issue: GitHub.