grpc/grpc-go · error
nil receiver passed to UnmarshalJSON
Error message
nil receiver passed to UnmarshalJSON
What it means
Returned by codes.Code.UnmarshalJSON when the receiver pointer itself is nil. The Code type implements json.Unmarshaler, so calling UnmarshalJSON on a nil *Code (instead of a *Code pointing to a valid Code value) has no valid destination to write the parsed code into. This is an internal/misuse error rather than a data error.
Solutions
- Ensure the Code receiver is non-nil before calling UnmarshalJSON: allocate a Code value and pass its address (e.g. var c Code; c.UnmarshalJSON(b)).
- Prefer json.Unmarshal over calling UnmarshalJSON directly so Go manages receiver allocation.
- If unmarshaling into a pointer-to-pointer, initialize the inner pointer before decoding.
Example fix
// before var c *codes.Code c.UnmarshalJSON([]byte(`"OK"`)) // nil receiver error // after var c codes.Code (&c).UnmarshalJSON([]byte(`"OK"`))
Defensive patterns
Strategy: validation
Validate before calling
// Before calling UnmarshalJSON, ensure the receiver is non-nil.
func safeUnmarshalCode(b []byte) (codes.Code, error) {
var c codes.Code
err := c.UnmarshalJSON(b) // c is addressable, receiver is &c
return c, err
} Type guard
// Prefer json.Unmarshal which allocates the target; only guard if calling manually.
func isCodeReceiverValid(c *codes.Code) bool {
return c != nil
} Prevention
- Never call (*Code)(nil).UnmarshalJSON directly; use json.Unmarshal into a *codes.Code.
- When writing custom JSON adapters, always allocate the target value before invoking UnmarshalJSON.
- Add a nil-receiver unit test to catch regressions in wrapper code.
When it happens
Trigger: Calling (*Code)(nil).UnmarshalJSON(b) directly, or json.Unmarshal into a **Code where the inner pointer is nil, or using reflection to invoke UnmarshalJSON on a nil Code pointer. The check at codes.go:232 guards against a nil receiver dereference panic.
Common situations: Custom JSON decoding wrappers that pass a nil *Code, or incorrect use of reflection-based serializers. In normal json.Unmarshal usage Go allocates the target so this is not hit; it surfaces in custom frameworks or test code that manually calls the method.
Related errors
- invalid code
- invalid code
- credentials: ctx cannot be nil
- error parsing observability config
- error parsing Outlier Detection config
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/2e01c0b6f43f6375.
Report an issue: GitHub.
Appendix: source
Thrown at codes/codes.go:233
`"ABORTED"`: Aborted,
`"OUT_OF_RANGE"`: OutOfRange,
`"UNIMPLEMENTED"`: Unimplemented,
`"INTERNAL"`: Internal,
`"UNAVAILABLE"`: Unavailable,
`"DATA_LOSS"`: DataLoss,
`"UNAUTHENTICATED"`: Unauthenticated,
}
// UnmarshalJSON unmarshals b into the Code.
func (c *Code) UnmarshalJSON(b []byte) error {
// From json.Unmarshaler: By convention, to approximate the behavior of
// Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
// a no-op.
if string(b) == "null" {
return nil
}
if c == nil {
return fmt.Errorf("nil receiver passed to UnmarshalJSON")
}
if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
if ci >= _maxCode {
return fmt.Errorf("invalid code: %d", ci)
}
*c = Code(ci)
return nil
}
if jc, ok := strToCode[string(b)]; ok {
*c = jc
return nil
}
return fmt.Errorf("invalid code: %q", string(b))
}
View on GitHub (pinned to 0c51461d27)