Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON-RPC errors standardization #728

Closed
AnnaShaleva opened this issue Jun 10, 2022 · 2 comments
Closed

JSON-RPC errors standardization #728

AnnaShaleva opened this issue Jun 10, 2022 · 2 comments

Comments

@AnnaShaleva
Copy link
Member

Background

Standard JSON-RPC error response contains three fields wrapped into error JSON structure to give a hint on what was wrong during failed JSON-RPC request processing. These fields are code, message and data (see ref):

private static JObject CreateErrorResponse(JObject id, int code, string message, JObject data = null)
        {
            JObject response = CreateResponse(id);
            response["error"] = new JObject();
            response["error"]["code"] = code;
            response["error"]["message"] = message;
            if (data != null)
                response["error"]["data"] = data;
            return response;
        }

data field contains exception stack trace in DEBUG mode and is always absent in non-DEBUG mode; message field contains the exception message that caused the RPC request failure; code field contains designated error code. Once JSON-RPC error is returned, RPC client can parse the code/message[/data] information and decide on further actions based on the error details.

Problem

After careful review of neo-modules and NeoGo code it can be stated that there are several groups of JSON-RPC error codes:

  • -32600-32700 are defined by the JSON-RPC specification and are used to report general request-related error information (invalid JSON/request structure/method/parameters or internal server error).

  • -500-505 are used to report various block/transaction/payload submit and relay errors (non-uniformly, NeoGo follows Legacy set of error codes, while C# node uses -500 only).

  • -400 is used to report unauthorized wallet-related access.

  • -300, -301 are used for wallet-related errors happened during funds transfer handling.

  • -100-102 are used for the rest of possible RPC errors (non-uniformly, NeoGo doesn’t use -101 and -102).

The most interesting (and the most frequently returned) range of errors is request-specific (-505-100). However, there are only a few subject-specific codes related to the blocks/transactions submission errors; other errors are hidden under the single shared code (e.g. -100) which makes it hard to recognize the specific error. At the same time there are cases when more fine-grained data about the request failure reason needs to be known to the JSON-RPC client. Currently, to distinguish such errors, the client's code has to parse error message strings which leads to reliability and compatibility problems.

Proposal

To avoid the described problem we need to standardize JSON-RPC error requirements and codes between different server (C#/Go) and client (a lot of them) implementations and extend the list of supported RPC error codes and messages. Our primary concern is everything that is currently hidden under -100 and -500 codes.

Standardization

The list of suggestions on JSON-RPC errors standardization is presented below.

  1. First of all, we suggest clarifying error’s code, message and data fields meaning and purpose. While the basic definition is given by the JSON-RPC specification we’d like to add some additional Neo-specific constraints to facilitate client-server interoperability. We suggest the following definitions:

    1. code field MUST be a negative integer value ranging from -1 to -65536 that is reserved for a particular error by the specification. code field MUST be the same for each Neo node irrespective of the implementation details except for the reserved experimental implementation-defined range. code field MUST NOT be omitted.

    2. message field MUST be a string value that specifies a short error description. message value MAY NOT be exactly the same across the Neo node implementations (we have code for this). message value SHOULD be limited to a concise single sentence. message field MUST NOT be omitted. message field SHOULD start with a capital letter and SHOULD NOT end with a dot.

    3. data field MUST be a string value that contains any implementation-dependent textual data (including debug traces). data field MAY be omitted, however it’s RECOMMENDED for servers to return it. data value SHOULD contain additional information about error and be aimed to clarify the error reason. data value MAY NOT be exactly the same across Neo node implementations.

  2. Error codes are grouped. We need to clarify the meaning of each codes group, so we suggest the following:

    1. -100-199 codes are reserved for errors connected with missing/unknown inventories or states. These error codes can be shared between multiple JSON-RPC methods and even between plugins.
    2. -200-299 codes are reserved for unclassified core RPC server plugin errors.
    3. -300-399 codes are reserved for wallet-related errors.
    4. -500-599 codes are reserved for various inventory verification errors.
    5. -600-699 are reserved for Oracle service (plugin) functionality errors.
    6. -700-799 are reserved for StateService (plugin) functionality errors.
    7. -800-899 are reserved for Notary service (plugin) functionality errors.
    8. -10000-15000 are reserved for experimental implementation-defined range of error codes specific for any custom node implementation. This range of codes is guaranteed not to be overlapped with any other set of current or future error codes and may be safely overridden by a custom node implementation.
    9. All the other codes are reserved for future use and MUST NOT be used by compliant implementations.

    Existing codes already defined in the code should be used with the same meaning where possible.

  3. Extend the list of supported method-specific JSON-RPC error codes and error messages hidden under -100 code:

    1. -101 “Unknown block”
    2. -102 “Unknown contract”
    3. -103 “Unknown transaction”
    4. -104 “Unknown storage item”
    5. -105 “Unknown script container”
    6. -106 “Unknown state root”
    7. -107 “Unknown header”
  4. Create a separate set of error codes for unclassified core RPC Server functionality errors, use -200-299 codes for it:

    1. -201 “Invalid height”
    2. -202 “Invalid verification function”
  5. Extend the list of supported method-specific wallet-related RPC error codes hidden under -300-399 codes and squash them with wallet access related error codes hidden under -400:

    1. -300 "Access denied"
    2. -301 “Wallet file not found”
    3. -303 “Wallet file not supported”
    4. -304 “Insufficient funds”
    5. -305 “Maximum transaction fee limit is exceeded”
  6. Extend the list of supported method-specific JSON-RPC error codes and error messages hidden under -500 code (inventory verification errors). This can be done by creating a separate error code for all possible values of VerifyResult. Moreover, it would be nice to specify corresponding error message inside the JSON-RPC error data field. Here’s the list of proposed relay-related JSON-RPC error codes with messages:

    1. -500 “Unclassified inventory verification error”
    2. -501 “Inventory already exists on chain”
    3. -502 “The memory pool is full and no more transactions can be sent”
    4. -503 “Transaction already exists in the memory pool” // Code -503 was used by Legacy with a meaning close to -504, but now it’s not used by any node implementation, thus we suggest changing its meaning.
    5. -504 “Validation failed”
    6. -505 “One of the Policy filters failed”
    7. -506 “Invalid script”
    8. -507 “Invalid transaction attribute”
    9. -508 “Invalid signature”
    10. -509 “Invalid inventory size”
    11. -510 “Expired transaction”
    12. -511 “Insufficient funds”
  7. Create a separate set of error codes for Oracle functionality, use -600-699 codes for it:

    1. -601 “Oracle service is not running”
    2. -602 “Oracle request has already been finished”
    3. -603 “Oracle request is not found”
    4. -604 “Not a designated oracle node”
  8. Create a separate set of errors for StateService functionality, use -700-799 codes for it:

    1. -701 “Old state requests are not supported”
    2. -702 “Invalid proof”
  9. Create a separate set of errors for Notary functionality, use -800-899 codes for it:

    1. -801 “Notary service is not running”
    2. -802 “Invalid fallback transaction sender”
    3. -803 “Fallback transaction is valid after deposit is unlocked”
    4. -804 “Not a designated notary node”
    5. -805 “Invalid notary request signature”

The table below contains the full set of JSON-RPC error codes returned for each method except the standard ones -32700-32600 defined by the JSON-RPC specification (which can be used in responses by any method).

Method Error code Error message example Error data description or content example
calculatenetworkfee -506 “Invalid signature” Contract verification for signer #%d failed.
closewallet
dumpprivkey -300 “Access denied”
findstates -701 “State requests are not supported”
-102 “Unknown contract”
getapplicationlog -105 “Unknown script container”
getblock -101 “Unknown block” Error/exception got while retrieving block
getblockhash -201 “Invalid height”
getblockheader -107 “Unknown header” Error/exception got while retrieving block
getcommittee
getconnectioncount
getcontractstate -102 “Unknown contract”
getnativecontracts
getnep11balances
getnep11properties
getnep11transfers
getnep17balances
getnep17transfers
getnewaddress -300 “Access denied”
getnextblockvalidators
getpeers
getproof -701 “State requests are not supported”
-102 “Unknown contract”
-104 “Unknown storage item”
getrawmempool
getrawtransaction -103 “Unknown transaction” Error/exception got while retrieving tx.
getstate -701 “State requests are not supported”
-102 “Unknown contract”
getstateheight
getstateroot -106 “Unknown state root” Error/exception got while retrieving stateroot.
getstorage -102 “Unknown contract”
-104 “Unknown storage item”
gettransactionheight -103 “Unknown transaction” Error/exception got while retrieving tx.
getunclaimedgas
getversion
getwalletbalance -300 “Access denied”
getwalletunclaimedgas -300 “Access denied”
invokecontractverify -102 “Unknown contract”
-202 “Invalid verification function” Missing verify method.
-202 “Invalid verification function” Invalid verify return value.
invokefunction
invokescript
importprivkey -300 “Access denied”
listaddress -300 “Access denied”
listplugins
openwallet -300 “Access denied”
-301 “Wallet file not found”
-302 “Wallet file not supported”
sendfrom / sendmany / sendtoaddress -300 “Access denied”
-304 “Insufficient funds”
-305 “Maximum transaction fee limit is exceeded”
sendrawtransaction -500-510 Additional exception message or transaction validation error data
submitblock -500-510 Additional exception message or block validation error data
submitnotaryrequest -801-805 Various notary-request specific errors.
-500-510 Various inventory verification errors.
submitoracleresponse -601-604
-506 “Invalid signature” Invalid oracle node signature.
validateaddress -32602* “Invalid params” Parameter index + detailed description of the reason why the parameter is invalid. *Currently C# node does not return any error in case if parameter is not valid (i.e. if it’s an array).
verifyproof -702 “Invalid proof”

Adjustments

There are also some C# implementation-specific adjustment suggestions:

  1. Unify case of commonly used error messages (-3260-3270):

    1. -32600 “Invalid Request” -> “Invalid request”
  2. Make -32602 “Invalid params” error more detailed:

    1. Add index of the invalid parameter to error’sdata.
    2. Add the exact reason of why the parameter is invalid to error’s data.
  3. Adjust documentation for each JSON-RPC method:

    1. Specify error codes that can be returned by each method. See the table above for details. Standard JSON-RPC errors defined by the JSON-RPC specification (-32700-32600) are omitted from the table for simplicity.

Conclusion

The primary concern of this issue is to have 100% compatible error codes that we could rely on in any JSON-RPC client and to have an explicitly defined error object structure. It can be evolved into a complete NEP where these codes could be maintained/extended and that could be used as a reference (extended by other NEPs in future). For now it’s more of an open discussion, any suggestions are welcome.

@roman-khimov
Copy link
Contributor

Addendum for recently added methods:

  • getcandidates
    Very similar to getnextblockvalidators, doesn't have any specific errors.
  • terminatesession and traverseiterator
    Three new codes are proposed:
    • -203 for "Sessions disabled", when RPC server is configured with SessionEnabled: false it'd be nice to return this error to the user for both of these calls
    • -108 "Unknown session" for requests that try to do something with a session that doesn't exist
      terminatesession effectively returns it as false result at the moment, but we can make it consistent with traverseiterator
    • -109 "Unknown iterator" for traverseiterator calls that try accessing iterator that doesn't exist in otherwise valid session

Notice that terminatesession and traverseiterator implementations currently have different behavior (#745).

roman-khimov added a commit to roman-khimov/proposals that referenced this issue Sep 13, 2022
Based on neo-project/neo-modules#728, but differs a bit from it:
 * reduced set of groups
 * unified missing block/header error
 * improved compatibility for -301 and -302
roman-khimov added a commit to roman-khimov/proposals that referenced this issue Sep 13, 2022
Based on neo-project/neo-modules#728, but differs a bit from it:
 * reduced set of groups
 * unified missing block/header error
 * improved compatibility for -301 and -302
@AnnaShaleva
Copy link
Member Author

This issue was opened as a discussion, the result of this issue is the RPC errors proposal (neo-project/proposals#156). Thus, I consider we may close this issue as completed and move further conversations directly to neo-project/proposals#156.

shargon added a commit to neo-project/proposals that referenced this issue Apr 4, 2024
* add RPC error proposal

Based on neo-project/neo-modules#728, but differs a bit from it:
 * reduced set of groups
 * unified missing block/header error
 * improved compatibility for -301 and -302

* nep-Y: correct group description

Co-authored-by: Erik van den Brink <git@erikvandenbrink.com>

* nep-Y: typo fix

Co-authored-by: Erik van den Brink <git@erikvandenbrink.com>

* nep-Y: unify -104 wording

Co-authored-by: Erik van den Brink <git@erikvandenbrink.com>

* nep-Y: UTF-8 for code/message

* nep-Y: clarify "other codes"

* nep-Y: the most specific

* NEP-Y: extend list of `getblock` and `getblockheader` return error codes

These can autoresolve height to hash, so height-related error code
is applicable as well.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>

* NEP-Y: extend list of `submitoracleresponse` return error codes

Oracle response can have invalid signature.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>

* NEP-Y: extend list of `submitblock` return error codes

Blocks contain transactions, therefore any transaction-related
error codes can be applicable too.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>

* NEP-Y: extend list of `verifyproof` return error codes

Proof verification is relevant only for the nodes that store not only
the latest chain state.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>

* nep-Y: add -600 for "access denied"

See neo-project/neo-modules#815 (comment)

Signed-off-by: Roman Khimov <roman@nspcc.ru>

* nep-Y: spelling fix

Signed-off-by: Roman Khimov <roman@nspcc.ru>

* Update nep-Y.mediawiki

Co-authored-by: Jimmy <jinghui@wayne.edu>

* Rename nep-Y.mediawiki to nep-23.mediawiki

* Update README.mediawiki

* Update nep-23.mediawiki

* Update README.mediawiki

* README: fix link to the document

Signed-off-by: Roman Khimov <roman@nspcc.ru>

* nep-23: add implementation links

Signed-off-by: Roman Khimov <roman@nspcc.ru>

* nep-23: extend -510 to cover NVB

Signed-off-by: Roman Khimov <roman@nspcc.ru>

* nep-23: add -513 for Conflicts

Signed-off-by: Roman Khimov <roman@nspcc.ru>

---------

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
Signed-off-by: Roman Khimov <roman@nspcc.ru>
Co-authored-by: Erik van den Brink <git@erikvandenbrink.com>
Co-authored-by: Anna Shaleva <shaleva.ann@nspcc.ru>
Co-authored-by: Shargon <shargon@gmail.com>
Co-authored-by: Jimmy <jinghui@wayne.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants