{"record":{"id":"e7d639db318e5ceb","repo":"grpc/grpc-go","slug":"no-error-details-for-status-with-code-ok","errorCode":null,"errorMessage":"no error details for status with code OK","messagePattern":"no error details for status with code OK","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/status/status.go","lineNumber":136,"sourceCode":"\tif s == nil {\n\t\treturn nil\n\t}\n\treturn proto.Clone(s.s).(*spb.Status)\n}\n\n// Err returns an immutable error representing s; returns nil if s.Code() is OK.\nfunc (s *Status) Err() error {\n\tif s.Code() == codes.OK {\n\t\treturn nil\n\t}\n\treturn &Error{s: s}\n}\n\n// WithDetails returns a new status with the provided details messages appended to the status.\n// If any errors are encountered, it returns nil and the first error encountered.\nfunc (s *Status) WithDetails(details ...protoadapt.MessageV1) (*Status, error) {\n\tif s.Code() == codes.OK {\n\t\treturn nil, errors.New(\"no error details for status with code OK\")\n\t}\n\t// s.Code() != OK implies that s.Proto() != nil.\n\tp := s.Proto()\n\tfor _, detail := range details {\n\t\tm, err := anypb.New(protoadapt.MessageV2Of(detail))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tp.Details = append(p.Details, m)\n\t}\n\treturn &Status{s: p}, nil\n}\n\n// Details returns a slice of details messages attached to the status.\n// If a detail cannot be decoded, the error is returned in place of the detail.\n// If the detail can be decoded, the proto message returned is of the same\n// type that was given to WithDetails().\nfunc (s *Status) Details() []any {","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/status/status.go#L118-L154","documentation":"Returned by Status.WithDetails when the Status has code OK. gRPC's status invariant dictates that an OK status represents success and must never carry error details (details are rich metadata for failures). WithDetails explicitly rejects adding details to an OK status to prevent creating a semantically contradictory state. Details are only meaningful attached to non-OK codes.","triggerScenarios":"Calling st.WithDetails(detailProto) on a Status created with status.New(codes.OK, \"\") or obtained from a successful RPC. This is a programming error—the caller should only attach details to failure statuses.","commonSituations":"Interceptor or handler code that attaches details unconditionally without checking the code; error-wrapping utilities that call WithDetails on whatever status they receive, including success; copy-paste from error-handling code into a success path.","solutions":["Only call WithDetails when the status code is not OK: check st.Code() != codes.OK first.","Construct the status with a non-OK code before adding details: status.New(codes.InvalidArgument, \"bad input\").","Refactor shared code to guard the WithDetails call with a code check.","If you need metadata on a successful response, use response headers/trailers, not status details."],"exampleFix":"// before\nst := status.New(codes.OK, \"success\")\nst, err := st.WithDetails(detail) // error!\n// after\nst := status.New(codes.InvalidArgument, \"invalid input\")\nst, err := st.WithDetails(detail) // ok\n\n// or guard:\nif st.Code() != codes.OK {\n    st, _ = st.WithDetails(detail)\n}","handlingStrategy":"validation","validationCode":"// Only call WithDetails on non-OK statuses.\nfunc safeWithDetails(st *status.Status, details ...protoadapt.MessageV1) (*status.Status, error) {\n    if st.Code() == codes.OK {\n        return st, nil // no details for success\n    }\n    return st.WithDetails(details...)\n}","typeGuard":null,"tryCatchPattern":"st, err := st.WithDetails(detail)\nif err != nil && strings.Contains(err.Error(), \"code OK\") {\n    // programming error: don't add details to OK status\n    log.Print(\"warning: attempted to add details to OK status\")\n}","preventionTips":["Check st.Code() != codes.OK before calling WithDetails.","Only construct statuses with non-OK codes when you intend to add details.","Use response metadata/headers for successful-response metadata instead of status details.","Review interceptors that wrap statuses to ensure they guard WithDetails calls."],"tags":["status","grpc","validation","error-handling"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}