blob: 58423032ab79844a91d95a48095a852dd3577727 [file] [log] [blame]
khenaidoo5fc5cea2021-08-11 17:39:16 -04001/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package status implements errors returned by gRPC. These errors are
20// serialized and transmitted on the wire between server and client, and allow
21// for additional data to be transmitted via the Details field in the status
22// proto. gRPC service handlers should return an error created by this
23// package, and gRPC clients should expect a corresponding error to be
24// returned from the RPC call.
25//
26// This package upholds the invariants that a non-nil error may not
27// contain an OK code, and an OK code must result in a nil error.
28package status
29
30import (
31 "context"
khenaidoo257f3192021-12-15 16:46:37 -050032 "errors"
khenaidoo5fc5cea2021-08-11 17:39:16 -040033 "fmt"
34
35 spb "google.golang.org/genproto/googleapis/rpc/status"
36
37 "google.golang.org/grpc/codes"
38 "google.golang.org/grpc/internal/status"
39)
40
41// Status references google.golang.org/grpc/internal/status. It represents an
42// RPC status code, message, and details. It is immutable and should be
43// created with New, Newf, or FromProto.
44// https://godoc.org/google.golang.org/grpc/internal/status
45type Status = status.Status
46
47// New returns a Status representing c and msg.
48func New(c codes.Code, msg string) *Status {
49 return status.New(c, msg)
50}
51
52// Newf returns New(c, fmt.Sprintf(format, a...)).
53func Newf(c codes.Code, format string, a ...interface{}) *Status {
54 return New(c, fmt.Sprintf(format, a...))
55}
56
57// Error returns an error representing c and msg. If c is OK, returns nil.
58func Error(c codes.Code, msg string) error {
59 return New(c, msg).Err()
60}
61
62// Errorf returns Error(c, fmt.Sprintf(format, a...)).
63func Errorf(c codes.Code, format string, a ...interface{}) error {
64 return Error(c, fmt.Sprintf(format, a...))
65}
66
67// ErrorProto returns an error representing s. If s.Code is OK, returns nil.
68func ErrorProto(s *spb.Status) error {
69 return FromProto(s).Err()
70}
71
72// FromProto returns a Status representing s.
73func FromProto(s *spb.Status) *Status {
74 return status.FromProto(s)
75}
76
khenaidoo5cb0d402021-12-08 14:09:16 -050077// FromError returns a Status representation of err.
78//
Joey Armstrongba3d9d12024-01-15 14:22:11 -050079// - If err was produced by this package or implements the method `GRPCStatus()
80// *Status`, the appropriate Status is returned.
khenaidoo5cb0d402021-12-08 14:09:16 -050081//
82// - If err is nil, a Status is returned with codes.OK and no message.
83//
Joey Armstrongba3d9d12024-01-15 14:22:11 -050084// - Otherwise, err is an error not compatible with this package. In this
85// case, a Status is returned with codes.Unknown and err's Error() message,
86// and ok is false.
khenaidoo5fc5cea2021-08-11 17:39:16 -040087func FromError(err error) (s *Status, ok bool) {
88 if err == nil {
89 return nil, true
90 }
91 if se, ok := err.(interface {
92 GRPCStatus() *Status
93 }); ok {
94 return se.GRPCStatus(), true
95 }
96 return New(codes.Unknown, err.Error()), false
97}
98
99// Convert is a convenience function which removes the need to handle the
100// boolean return value from FromError.
101func Convert(err error) *Status {
102 s, _ := FromError(err)
103 return s
104}
105
106// Code returns the Code of the error if it is a Status error, codes.OK if err
107// is nil, or codes.Unknown otherwise.
108func Code(err error) codes.Code {
109 // Don't use FromError to avoid allocation of OK status.
110 if err == nil {
111 return codes.OK
112 }
113 if se, ok := err.(interface {
114 GRPCStatus() *Status
115 }); ok {
116 return se.GRPCStatus().Code()
117 }
118 return codes.Unknown
119}
120
khenaidoo257f3192021-12-15 16:46:37 -0500121// FromContextError converts a context error or wrapped context error into a
122// Status. It returns a Status with codes.OK if err is nil, or a Status with
123// codes.Unknown if err is non-nil and not a context error.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400124func FromContextError(err error) *Status {
khenaidoo257f3192021-12-15 16:46:37 -0500125 if err == nil {
khenaidoo5fc5cea2021-08-11 17:39:16 -0400126 return nil
khenaidoo5fc5cea2021-08-11 17:39:16 -0400127 }
khenaidoo257f3192021-12-15 16:46:37 -0500128 if errors.Is(err, context.DeadlineExceeded) {
129 return New(codes.DeadlineExceeded, err.Error())
130 }
131 if errors.Is(err, context.Canceled) {
132 return New(codes.Canceled, err.Error())
133 }
134 return New(codes.Unknown, err.Error())
khenaidoo5fc5cea2021-08-11 17:39:16 -0400135}