diff --git a/common/errors/codes.go b/common/errors/codes.go new file mode 100644 index 00000000000..dd723afd58a --- /dev/null +++ b/common/errors/codes.go @@ -0,0 +1,104 @@ +/* + Copyright Digital Asset Holdings, LLC 2016 All Rights Reserved. + Copyright IBM Corp. 2017 All Rights Reserved. + + 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 errors + +// A set of constants for error reason codes, which is based on HTTP codes +// http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml +const ( + // Invalid inputs on API calls + BadRequest = "400" + + // Forbidden due to access control issues + Forbidden = "403" + + // Not Found (eg chaincode not found) + NotFound = "404" + + // Request timeout (chaincode or ledger) + Timeout = "408" + + // Example, duplicate transactions or replay attacks + Conflict = "409" + + // Request for resource is not available. Example, a chaincode has + // been upgraded and the request uses an old version + Gone = "410" + + // Payload of the request exceeds allowed size + PayloadTooLarge = "413" + + // Example, marshal/unmarshalling protobuf error + UnprocessableEntity = "422" + + // Protocol version is no longer supported + UpgradeRequired = "426" + + // Internal server errors that are not classified below + Internal = "500" + + // Requested chaincode function has not been implemented + NotImplemented = "501" + + // Requested chaincode is not available + Unavailable = "503" + + // File IO errors + FileIO = "520" + + // Network IO errors + NetworkIO = "521" +) + +// A set of constants for component codes +const ( + // BCCSP is fabic/BCCSP + BCCSP = "CSP" + + // Common is fabric/common + Common = "CMN" + + // Core is fabric/core + Core = "COR" + + // Event is fabric/events component + Event = "EVT" + + // Gossip is fabric/gossip + Gossip = "GSP" + + // Ledger is fabric/core/ledger + Ledger = "LGR" + + // Peer is fabric/peer + Peer = "PER" + + // Orderer is fabric/orderer + Orderer = "ORD" + + // MSP is fabric/msp + MSP = "MSP" + + // ChaincodeSupport is fabric/core/chaincode + ChaincodeSupport = "CCS" + + // DeliveryService is fabric/core/deliverservice + DeliveryService = "CDS" + + // SystemChaincode is fabric/core/scc (system chaincode) + SystemChaincode = "SCC" +) diff --git a/common/errors/errors_test.go b/common/errors/errors_test.go index b67f14a2c46..1ea523e3c02 100644 --- a/common/errors/errors_test.go +++ b/common/errors/errors_test.go @@ -37,15 +37,15 @@ func TestError(t *testing.T) { var tc []testCase tc = append(tc, - testCase{"UnknownErrorWithCallstack", []string{"UNK", "404", "An unknown error occurred."}, nil, nil, nil, []bool{true}}, - testCase{"UnknownError", []string{"UNK", "404", "An unknown error occurred."}, nil, nil, nil, []bool{false}}, - testCase{"UnknownErrorWithCallstackAndArg", []string{"UNK", "405", "An error occurred: %s"}, []string{"arg1"}, nil, nil, []bool{true}}, - testCase{"UnknownErrorWithArg", []string{"UNK", "405", "An error occurred: %s"}, []string{"arg1"}, nil, nil, []bool{false}}, - testCase{"CallStackErrorWrappedCallstackError", []string{"CHA", "404", "An unknown error occurred."}, nil, []string{"UNK", "404", "An unknown error occurred."}, nil, []bool{true, true}}, - testCase{"ErrorWrappedError", []string{"CHA", "404", "An unknown error occurred."}, nil, []string{"UNK", "404", "An unknown error occurred."}, nil, []bool{false, false}}, - testCase{"CallStackErrorWrappedError", []string{"CHA", "404", "An unknown error occurred."}, nil, []string{"UNK", "404", "An unknown error occurred."}, nil, []bool{true, false}}, - testCase{"ErrorWrappedCallStackError", []string{"CHA", "404", "An unknown error occurred."}, nil, []string{"UNK", "404", "An unknown error occurred."}, nil, []bool{false, true}}, - testCase{"ErrorWrappedStandardError", []string{"CHA", "404", "An unknown error occurred."}, nil, []string{"grpc timed out: %s"}, []string{"failed to connect to server"}, []bool{false, true}}, + testCase{"UnknownErrorWithCallstack", []string{Core, NotFound, "An unknown error occurred."}, nil, nil, nil, []bool{true}}, + testCase{"UnknownError", []string{MSP, Forbidden, "An unknown error occurred."}, nil, nil, nil, []bool{false}}, + testCase{"UnknownErrorWithCallstackAndArg", []string{Ledger, Conflict, "An error occurred: %s"}, []string{"arg1"}, nil, nil, []bool{true}}, + testCase{"UnknownErrorWithArg", []string{SystemChaincode, Internal, "An error occurred: %s"}, []string{"arg1"}, nil, nil, []bool{false}}, + testCase{"CallStackErrorWrappedCallstackError", []string{BCCSP, NotImplemented, "An unknown error occurred."}, nil, []string{Peer, UpgradeRequired, "An unknown error occurred."}, nil, []bool{true, true}}, + testCase{"ErrorWrappedError", []string{Common, Unavailable, "An unknown error occurred."}, nil, []string{SystemChaincode, Gone, "An unknown error occurred."}, nil, []bool{false, false}}, + testCase{"CallStackErrorWrappedError", []string{Event, Timeout, "An unknown error occurred."}, nil, []string{Orderer, NetworkIO, "An unknown error occurred."}, nil, []bool{true, false}}, + testCase{"ErrorWrappedCallStackError", []string{Orderer, UnprocessableEntity, "An unknown error occurred."}, nil, []string{"UNK", "404", "An unknown error occurred."}, nil, []bool{false, true}}, + testCase{"ErrorWrappedStandardError", []string{DeliveryService, Unavailable, "An unknown error occurred."}, nil, []string{"grpc timed out: %s"}, []string{"failed to connect to server"}, []bool{false, true}}, ) assert := assert.New(t) diff --git a/docs/source/error-handling.rst b/docs/source/error-handling.rst index edf435bed44..db4065e5490 100644 --- a/docs/source/error-handling.rst +++ b/docs/source/error-handling.rst @@ -11,23 +11,14 @@ A CallStackError consists of the following: - Component code - a name for the general area of the code that is generating the error. Component codes should consist of three uppercase letters. Numerics - and special characters are not allowed. - -.. note:: Make sure to use a consistent component name across code in related - files/packages. - Examples of component codes (with their full component name in parentheses) - are: CSP (bccsp), CMN (common), COR (core), CCS (core/chaincode), CDS - (core/deliverservice), SCC (core/scc), EVT (events), GSP (gossip), LGR - (ledger), PER (peer), ORD (orderer) - -We may, in the future, add constants to allow searching for currently defined -components for those using an editor with code completion capabilities. - + and special characters are not allowed. A set of component codes is defined + in common/errors/codes.go - Reason code - a short code to help identify the reason the error occurred. Reason codes should consist of three numeric values. Letters and special - characters are not allowed. + characters are not allowed. A set of reason codes is defined in + common/error/codes.go - Error code - the component code and reason code separated by a colon, - e.g. PER:404 + e.g. MSP:404 - Error message - the text that describes the error. This is the same as the input provided to ``fmt.Errorf()`` and ``Errors.New()``. If an error has been wrapped into the current error, its message will be appended. @@ -39,9 +30,9 @@ The CallStackError interface exposes the following functions: - Error() - returns the error message with callstack appended - Message() - returns the error message (without callstack appended) -- GetComponentCode() -- GetReasonCode() -- GetErrorCode() +- GetComponentCode() - returns the 3-character component code +- GetReasonCode() - returns the 3-digit reason code +- GetErrorCode() - returns the error code, which is "component:reason" - GetStack() - returns just the callstack - WrapError(error) - wraps the provided error into the CallStackError