1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
// Copyright 2021-2023 The Connect Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package connect
import (
"fmt"
"strconv"
"strings"
)
// A Code is one of the Connect protocol's error codes. There are no user-defined
// codes, so only the codes enumerated below are valid. In both name and
// semantics, these codes match the gRPC status codes.
//
// The descriptions below are optimized for brevity rather than completeness.
// See the [Connect protocol specification] for detailed descriptions of each
// code and example usage.
//
// [Connect protocol specification]: https://connectrpc.com/docs/protocol
type Code uint32
const (
// The zero code in gRPC is OK, which indicates that the operation was a
// success. We don't define a constant for it because it overlaps awkwardly
// with Go's error semantics: what does it mean to have a non-nil error with
// an OK status? (Also, the Connect protocol doesn't use a code for
// successes.)
// CodeCanceled indicates that the operation was canceled, typically by the
// caller.
CodeCanceled Code = 1
// CodeUnknown indicates that the operation failed for an unknown reason.
CodeUnknown Code = 2
// CodeInvalidArgument indicates that client supplied an invalid argument.
CodeInvalidArgument Code = 3
// CodeDeadlineExceeded indicates that deadline expired before the operation
// could complete.
CodeDeadlineExceeded Code = 4
// CodeNotFound indicates that some requested entity (for example, a file or
// directory) was not found.
CodeNotFound Code = 5
// CodeAlreadyExists indicates that client attempted to create an entity (for
// example, a file or directory) that already exists.
CodeAlreadyExists Code = 6
// CodePermissionDenied indicates that the caller doesn't have permission to
// execute the specified operation.
CodePermissionDenied Code = 7
// CodeResourceExhausted indicates that some resource has been exhausted. For
// example, a per-user quota may be exhausted or the entire file system may
// be full.
CodeResourceExhausted Code = 8
// CodeFailedPrecondition indicates that the system is not in a state
// required for the operation's execution.
CodeFailedPrecondition Code = 9
// CodeAborted indicates that operation was aborted by the system, usually
// because of a concurrency issue such as a sequencer check failure or
// transaction abort.
CodeAborted Code = 10
// CodeOutOfRange indicates that the operation was attempted past the valid
// range (for example, seeking past end-of-file).
CodeOutOfRange Code = 11
// CodeUnimplemented indicates that the operation isn't implemented,
// supported, or enabled in this service.
CodeUnimplemented Code = 12
// CodeInternal indicates that some invariants expected by the underlying
// system have been broken. This code is reserved for serious errors.
CodeInternal Code = 13
// CodeUnavailable indicates that the service is currently unavailable. This
// is usually temporary, so clients can back off and retry idempotent
// operations.
CodeUnavailable Code = 14
// CodeDataLoss indicates that the operation has resulted in unrecoverable
// data loss or corruption.
CodeDataLoss Code = 15
// CodeUnauthenticated indicates that the request does not have valid
// authentication credentials for the operation.
CodeUnauthenticated Code = 16
minCode = CodeCanceled
maxCode = CodeUnauthenticated
)
func (c Code) String() string {
switch c {
case CodeCanceled:
return "canceled"
case CodeUnknown:
return "unknown"
case CodeInvalidArgument:
return "invalid_argument"
case CodeDeadlineExceeded:
return "deadline_exceeded"
case CodeNotFound:
return "not_found"
case CodeAlreadyExists:
return "already_exists"
case CodePermissionDenied:
return "permission_denied"
case CodeResourceExhausted:
return "resource_exhausted"
case CodeFailedPrecondition:
return "failed_precondition"
case CodeAborted:
return "aborted"
case CodeOutOfRange:
return "out_of_range"
case CodeUnimplemented:
return "unimplemented"
case CodeInternal:
return "internal"
case CodeUnavailable:
return "unavailable"
case CodeDataLoss:
return "data_loss"
case CodeUnauthenticated:
return "unauthenticated"
}
return fmt.Sprintf("code_%d", c)
}
// MarshalText implements [encoding.TextMarshaler].
func (c Code) MarshalText() ([]byte, error) {
return []byte(c.String()), nil
}
// UnmarshalText implements [encoding.TextUnmarshaler].
func (c *Code) UnmarshalText(data []byte) error {
dataStr := string(data)
switch dataStr {
case "canceled":
*c = CodeCanceled
return nil
case "unknown":
*c = CodeUnknown
return nil
case "invalid_argument":
*c = CodeInvalidArgument
return nil
case "deadline_exceeded":
*c = CodeDeadlineExceeded
return nil
case "not_found":
*c = CodeNotFound
return nil
case "already_exists":
*c = CodeAlreadyExists
return nil
case "permission_denied":
*c = CodePermissionDenied
return nil
case "resource_exhausted":
*c = CodeResourceExhausted
return nil
case "failed_precondition":
*c = CodeFailedPrecondition
return nil
case "aborted":
*c = CodeAborted
return nil
case "out_of_range":
*c = CodeOutOfRange
return nil
case "unimplemented":
*c = CodeUnimplemented
return nil
case "internal":
*c = CodeInternal
return nil
case "unavailable":
*c = CodeUnavailable
return nil
case "data_loss":
*c = CodeDataLoss
return nil
case "unauthenticated":
*c = CodeUnauthenticated
return nil
}
// Ensure that non-canonical codes round-trip through MarshalText and
// UnmarshalText.
if strings.HasPrefix(dataStr, "code_") {
dataStr = strings.TrimPrefix(dataStr, "code_")
code, err := strconv.ParseInt(dataStr, 10 /* base */, 64 /* bitsize */)
if err == nil && (code < int64(minCode) || code > int64(maxCode)) {
*c = Code(code)
return nil
}
}
return fmt.Errorf("invalid code %q", dataStr)
}
// CodeOf returns the error's status code if it is or wraps an [*Error] and
// [CodeUnknown] otherwise.
func CodeOf(err error) Code {
if connectErr, ok := asError(err); ok {
return connectErr.Code()
}
return CodeUnknown
}
|