Description
Problem
The RPC specification implements a subset of the JSON-RPC specification. It defines the available RPC methods together with in- and outputs and serialisation format. It however doesn't specify anything about the errors these methods can return. As a result implementations return different errors which makes it hard for DApp developers to act appropriately. Another problem is that currently there are no well defined errors codes. This causes some clients (e.g. Mist) to do string matching to determine what happened. This is brittle and not generic.
Proposal
Define a standard for Ethereum JSON-RPC errors. One of the problems is finding the correct balans between informing a DApp what happend and being not too specific. Being too specific will make it hard to become fully complient with the specification and would make DApp's more complicated. Being too generic DApps' won't be able to determine what happened.
This problem is tackled by introducing the concept of an error category and allow a node to supply optional extra information about an error. This allows a DApp to get a general understanding what went wrong by looking at the category error code. It also allow a node to provide additional information about an error which the DApp can decide to use.
This proposal contains 2 parts. First it describes how the errors are defined. The second part describes a list with standardized error categories and detailed error messages.
Error structure
JSON-RPC 2.0 has a section dedicated how errors are defined. The code
field will be used for an error category. This field is mandatory and used by DApp's to get a general understanding what happend. Together with the code
field the message
field is filled with a brief description about the category. See for more information about available categories and their description the next section.
The data
field is an optional field. Nodes can decide to supply additonal information through this field. If a node provides detailed information the data field must be an array of objects with the following fields:
field | type | mandatory |
---|---|---|
code | integer | yes |
description | string | no |
By using this approach DApp's can get a general understanding what happend through the code
field. In most cases this is sufficient. It also allow nodes to supply additional information when available.
Error categories
The JSON-RPC 2.0 specification defines the range -32000 to -32099 for application specific errors.
code | category | meaning |
---|---|---|
-32000 | INVALID_VALUE | parameter contains invalid value |
-32001 | NOT_FOUND | requested resource not found |
-32002 | UNAVAILABLE | resource not available |
-32003 | TX_REJECTED | transaction rejected |
-32099 | MISC | error, allow nodes to send custom errors |
Error details
If a node wants to send additional information about an error it can use the data
field.
category | code | meaning |
---|---|---|
INVALID_VALUE | 0 | invalid input, e.g. missing mandatory input |
TX_REJECTED | 0 | invalid nonce |
TX_REJECTED | 1 | unable to sign transaction |
TX_REJECTED | 2 | transaction already in tx pool |
TX_REJECTED | 3 | transaction gas price too low for acceptance |
TX_REJECTED | 4 | sender account doesn't exists |
TX_REJECTED | 5 | gas limit exceeds block gas limit |
TX_REJECTED | 6 | insufficient funds |
TX_REJECTED | 7 | insufficient intrinsic gas |
TX_REJECTED | 8 | from account is locked |
* | 99 | implementation specific field |
It is worth noting that 99
is a general code that can be used in any of the categories. It allows a node to provide non-standarised information to a DApp. Also this table doesn't specify the description
field. Nodes are free to choose what they put into the description
field, it is allowed to omit the description
field.
Example
Value transaction from an account with a balance of 0. The node determines this transaction will always fail and rejects the transaction. The returned error would look like:
{"jsonrpc": "2.0", "error": {"code": -32003, "message": "transaction rejected", "data":[{"code": 6, "description": "insufficient funds"}]}, "id": 1234}
The node doesn't uses the account management most implementations provides but forwards a transaction to an external signing service. When this service could not be reached the node can return the following error:
{"jsonrpc": "2.0", "error": {"code": -32003, "message": "transaction rejected", "data":[{"code": 1, "description": "unable to sign transaction"},{"code": 99, "description": "signing service not available"}]}, "id": null}
Required changes
- the rpc-test suite needs to be updated
- implementations must be updated