grpc/grpc-go · error
invalid code
Error message
invalid code: %q
What it means
Returned by codes.Code.UnmarshalJSON when the JSON input is a string token (with surrounding quotes) that does not match any known canonical gRPC code name in the strToCode map (OK, CANCELLED, UNKNOWN, INVALID_ARGUMENT, DEADLINE_EXCEEDED, NOT_FOUND, ALREADY_EXISTS, PERMISSION_DENIED, RESOURCE_EXHAUSTED, FAILED_PRECONDITION, ABORTED, OUT_OF_RANGE, UNIMPLEMENTED, INTERNAL, UNAVAILABLE, DATA_LOSS, UNAUTHENTICATED).
Solutions
- Use the exact canonical UPPER_SNAKE_CASE name from the strToCode map (note CANCELLED is British spelling with two L's).
- Send numeric codes as bare JSON numbers (no quotes) within [0,16] instead of strings.
- Validate/gateway external string values against codes.Code.String() or a known enum before producing the JSON.
Example fix
// before var c codes.Code json.Unmarshal([]byte(`"CANCEL"`), &c) // invalid code: "CANCEL" (missing an L) // after var c codes.Code json.Unmarshal([]byte(`"CANCELLED"`), &c) // canonical name
Defensive patterns
Strategy: validation
Validate before calling
var validCodeNames = map[string]bool{
`"OK"`: true, `"CANCELLED"`: true, `"UNKNOWN"`: true, `"INVALID_ARGUMENT"`: true,
`"DEADLINE_EXCEEDED"`: true, `"NOT_FOUND"`: true, `"ALREADY_EXISTS"`: true,
`"PERMISSION_DENIED"`: true, `"RESOURCE_EXHAUSTED"`: true, `"FAILED_PRECONDITION"`: true,
`"ABORTED"`: true, `"OUT_OF_RANGE"`: true, `"UNIMPLEMENTED"`: true, `"INTERNAL"`: true,
`"UNAVAILABLE"`: true, `"DATA_LOSS"`: true, `"UNAUTHENTICATED"`: true,
}
func isValidCodeJSONToken(b []byte) bool {
_, ok1 := strconv.ParseUint(string(b), 10, 32) // numeric ok if < 17
return ok1 == nil || validCodeNames[string(b)]
} Type guard
func isCanonicalCodeName(s string) bool {
return validCodeNames[strconv.Quote(s)]
} Prevention
- Always use the exact canonical UPPER_SNAKE_CASE names; remember CANCELLED is British spelling.
- Prefer numeric encoding (bare JSON number in [0,16]) for machine-to-machine interchange.
- Generate code names from codes.Code.String() rather than hand-typing them.
When it happens
Trigger: Unmarshaling JSON containing a quoted string that is not one of the 17 recognized code names — e.g. "FOO", "CANCEL" (missing an L; the canonical name is CANCELLED), "not_found" (lowercase), or "5" (a number inside quotes, which ParseUint rejects due to the quotes and strToCode also rejects).
Common situations: A typo in the code name, using lowercase instead of UPPER_SNAKE_CASE, using a different naming convention (e.g. HTTP status text like "NOT_FOUND" is valid but "Not Found" is not), or a non-gRPC service emitting its own string error identifiers into the same field.
Related errors
- invalid code
- nil receiver passed to UnmarshalJSON
- least-request: unable to unmarshal LBConfig
- pickfirst: unable to unmarshal LB policy config
- randomsubsetting: json.Unmarshal failed for configuration
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/6ec3595a8a476f04.
Report an issue: GitHub.
Appendix: source
Thrown at codes/codes.go:249
}
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)