go.etcd.io/etcd@v3.3.27+incompatible/error/error.go (about) 1 // Copyright 2015 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package error describes errors in etcd project. When any change happens, 16 // Documentation/v2/errorcode.md needs to be updated correspondingly. 17 package error 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "net/http" 23 ) 24 25 var errors = map[int]string{ 26 // command related errors 27 EcodeKeyNotFound: "Key not found", 28 EcodeTestFailed: "Compare failed", //test and set 29 EcodeNotFile: "Not a file", 30 ecodeNoMorePeer: "Reached the max number of peers in the cluster", 31 EcodeNotDir: "Not a directory", 32 EcodeNodeExist: "Key already exists", // create 33 ecodeKeyIsPreserved: "The prefix of given key is a keyword in etcd", 34 EcodeRootROnly: "Root is read only", 35 EcodeDirNotEmpty: "Directory not empty", 36 ecodeExistingPeerAddr: "Peer address has existed", 37 EcodeUnauthorized: "The request requires user authentication", 38 39 // Post form related errors 40 ecodeValueRequired: "Value is Required in POST form", 41 EcodePrevValueRequired: "PrevValue is Required in POST form", 42 EcodeTTLNaN: "The given TTL in POST form is not a number", 43 EcodeIndexNaN: "The given index in POST form is not a number", 44 ecodeValueOrTTLRequired: "Value or TTL is required in POST form", 45 ecodeTimeoutNaN: "The given timeout in POST form is not a number", 46 ecodeNameRequired: "Name is required in POST form", 47 ecodeIndexOrValueRequired: "Index or value is required", 48 ecodeIndexValueMutex: "Index and value cannot both be specified", 49 EcodeInvalidField: "Invalid field", 50 EcodeInvalidForm: "Invalid POST form", 51 EcodeRefreshValue: "Value provided on refresh", 52 EcodeRefreshTTLRequired: "A TTL must be provided on refresh", 53 54 // raft related errors 55 EcodeRaftInternal: "Raft Internal Error", 56 EcodeLeaderElect: "During Leader Election", 57 58 // etcd related errors 59 EcodeWatcherCleared: "watcher is cleared due to etcd recovery", 60 EcodeEventIndexCleared: "The event in requested index is outdated and cleared", 61 ecodeStandbyInternal: "Standby Internal Error", 62 ecodeInvalidActiveSize: "Invalid active size", 63 ecodeInvalidRemoveDelay: "Standby remove delay", 64 65 // client related errors 66 ecodeClientInternal: "Client Internal Error", 67 } 68 69 var errorStatus = map[int]int{ 70 EcodeKeyNotFound: http.StatusNotFound, 71 EcodeNotFile: http.StatusForbidden, 72 EcodeDirNotEmpty: http.StatusForbidden, 73 EcodeUnauthorized: http.StatusUnauthorized, 74 EcodeTestFailed: http.StatusPreconditionFailed, 75 EcodeNodeExist: http.StatusPreconditionFailed, 76 EcodeRaftInternal: http.StatusInternalServerError, 77 EcodeLeaderElect: http.StatusInternalServerError, 78 } 79 80 const ( 81 EcodeKeyNotFound = 100 82 EcodeTestFailed = 101 83 EcodeNotFile = 102 84 ecodeNoMorePeer = 103 85 EcodeNotDir = 104 86 EcodeNodeExist = 105 87 ecodeKeyIsPreserved = 106 88 EcodeRootROnly = 107 89 EcodeDirNotEmpty = 108 90 ecodeExistingPeerAddr = 109 91 EcodeUnauthorized = 110 92 93 ecodeValueRequired = 200 94 EcodePrevValueRequired = 201 95 EcodeTTLNaN = 202 96 EcodeIndexNaN = 203 97 ecodeValueOrTTLRequired = 204 98 ecodeTimeoutNaN = 205 99 ecodeNameRequired = 206 100 ecodeIndexOrValueRequired = 207 101 ecodeIndexValueMutex = 208 102 EcodeInvalidField = 209 103 EcodeInvalidForm = 210 104 EcodeRefreshValue = 211 105 EcodeRefreshTTLRequired = 212 106 107 EcodeRaftInternal = 300 108 EcodeLeaderElect = 301 109 110 EcodeWatcherCleared = 400 111 EcodeEventIndexCleared = 401 112 ecodeStandbyInternal = 402 113 ecodeInvalidActiveSize = 403 114 ecodeInvalidRemoveDelay = 404 115 116 ecodeClientInternal = 500 117 ) 118 119 type Error struct { 120 ErrorCode int `json:"errorCode"` 121 Message string `json:"message"` 122 Cause string `json:"cause,omitempty"` 123 Index uint64 `json:"index"` 124 } 125 126 func NewRequestError(errorCode int, cause string) *Error { 127 return NewError(errorCode, cause, 0) 128 } 129 130 func NewError(errorCode int, cause string, index uint64) *Error { 131 return &Error{ 132 ErrorCode: errorCode, 133 Message: errors[errorCode], 134 Cause: cause, 135 Index: index, 136 } 137 } 138 139 // Error is for the error interface 140 func (e Error) Error() string { 141 return e.Message + " (" + e.Cause + ")" 142 } 143 144 func (e Error) toJsonString() string { 145 b, _ := json.Marshal(e) 146 return string(b) 147 } 148 149 func (e Error) StatusCode() int { 150 status, ok := errorStatus[e.ErrorCode] 151 if !ok { 152 status = http.StatusBadRequest 153 } 154 return status 155 } 156 157 func (e Error) WriteTo(w http.ResponseWriter) error { 158 w.Header().Add("X-Etcd-Index", fmt.Sprint(e.Index)) 159 w.Header().Set("Content-Type", "application/json") 160 w.WriteHeader(e.StatusCode()) 161 _, err := w.Write([]byte(e.toJsonString() + "\n")) 162 return err 163 }