grpc/grpc-go · error
no error details for status with code OK
Error message
no error details for status with code OK
What it means
Returned by (*Status).WithDetails when the receiver Status has code codes.OK. gRPC forbids attaching rich error detail messages to a non-error status, since details are part of the error contract. WithDetails is only meaningful on statuses that represent an actual failure. The guard sits at internal/status/status.go:135-137 and returns a plain errors.New value.
Source
Thrown at internal/status/status.go:136
if s == nil {
return nil
}
return proto.Clone(s.s).(*spb.Status)
}
// Err returns an immutable error representing s; returns nil if s.Code() is OK.
func (s *Status) Err() error {
if s.Code() == codes.OK {
return nil
}
return &Error{s: s}
}
// WithDetails returns a new status with the provided details messages appended to the status.
// If any errors are encountered, it returns nil and the first error encountered.
func (s *Status) WithDetails(details ...protoadapt.MessageV1) (*Status, error) {
if s.Code() == codes.OK {
return nil, errors.New("no error details for status with code OK")
}
// s.Code() != OK implies that s.Proto() != nil.
p := s.Proto()
for _, detail := range details {
m, err := anypb.New(protoadapt.MessageV2Of(detail))
if err != nil {
return nil, err
}
p.Details = append(p.Details, m)
}
return &Status{s: p}, nil
}
// Details returns a slice of details messages attached to the status.
// If a detail cannot be decoded, the error is returned in place of the detail.
// If the detail can be decoded, the proto message returned is of the same
// type that was given to WithDetails().
func (s *Status) Details() []any {View on GitHub (pinned to 03255a9237)
Solutions
- Only call WithDetails when s.Code() != codes.OK; guard with an if before attaching details.
- If you genuinely have no error, skip the WithDetails call entirely and return the OK status unchanged.
- Use status.New with an explicit failing code (e.g. codes.Internal) before adding details.
- Refactor helpers to take a *status.Status and early-return on OK instead of always appending details.
Example fix
// before
st := status.New(codes.OK, "")
newSt, err := st.WithDetails(detail) // returns error
// after
st := status.New(codes.Internal, "boom")
if st.Code() != codes.OK {
newSt, err = st.WithDetails(detail)
} Defensive patterns
Strategy: validation
Validate before calling
func safeWithDetails(st *status.Status, details ...protoadapt.MessageV1) (*status.Status, error) {
if st.Code() == codes.OK {
return st, nil // nothing to attach
}
return st.WithDetails(details...)
} Type guard
func isErrorStatus(st *status.Status) bool { return st != nil && st.Code() != codes.OK } Prevention
- Never call WithDetails unconditionally; branch on code != OK first.
- Treat OK statuses as success and skip detail attachment.
- Write helpers that accept a Status and decide internally whether to enrich it.
When it happens
Trigger: Calling status.New(codes.OK, "").WithDetails(detail), or invoking WithDetails on a Status whose code was never changed from the zero value (OK). Also happens when reusing a Status returned from a prior call that resolved to OK and then unconditionally chaining WithDetails.
Common situations: Programmatically building a status and forgetting to set a non-OK code; helper functions that always call WithDetails without checking whether an upstream call actually failed; copying error-detail logic from a failing path into a success path.
Related errors
- duplicated name
- wrr: errorUtilizationPenalty must be non-negative
- %s: %v
- invalid code: %d
- invalid code: %q
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/e7d639db318e5ceb.
Report an issue: GitHub.