ethereum / ethereum/execution-apis
Call to Standardize `debug` Methods
- Dominant language
- Io
- Stars
- 1.1k
- Forks
- 530
- Avg merge
- 5d 8h
- Merged PRs (30d)
- 9
Description
### Overview
Hello developers,
I'm running a devnet chain for JSON-RPC testing. During testing, I noticed discrepancies in the JSON-RPC responses of `debug_` methods among geth, besu, nethermind, and reth.
In general, we have observed inconsistencies in debug method responses across four execution clients. Unlike the Engine API—which provides well-defined error codes and messages—the debug methods lack standardized error specifications. This absence of well-defined error codes and messages leads to inconsistent behavior and complicates the debugging process.
For example, according to the [execution-apis schema](https://ethereum.github.io/execution-apis/api-documentation/), the method `debug_getRawBlock` is expected to return an RLP-encoded block. However, the specification does not define the error behavior when the requested block is not found.
Since the purpose of execution-apis is to enable downstream tooling and infrastructure to treat different Ethereum clients as modules, we believe it is important to standardize the return of error codes and messages for debug methods as well.
Thanks for your attenntion.
Related methods:
- debug_getBadBlocks
- debug_getRawBlock
- debug_getRawHeader
- debug_getRawReceipts
- debug_getRawTransaction
### Clients
Tested client version.
Consensus
- Prysm/v6.0.0 (linux amd64)
- Lighthouse/v7.0.1-e42406d/x86_64-linux
- Nimbus/v25.4.1-77cfa7-stateofus
- Teku/v25.4.1/linux-x86_64/-eclipseadoptium-openjdk64bitservervm-java-21
Execution
- Geth/v1.15.12-unstable-3e356d69-20250507/linux-amd64/go1.24.3
- Besu/v25.4.1/linux-x86_64/openjdk-java-21
- Nethermind/v1.32.0-unstable+ff9befb5/linux-x64/dotnet9.0.4
- Reth/v1.3.12-6f8e725/x86_64-unknown-linux-gnu
### Results
Please note that we locally add `server` field in the response json for information and sort the key.
#### debug_getBadBlocks
debug_getBadBlocks. Reth didn't implemented this. see [issue](https://github.com/paradigmxyz/reth/issues/16132).
```json
# geth
{"id": 1, "jsonrpc": "2.0", "result": [], "server": "http://127.0.0.1:56406"}
# besu
{"id": 1, "jsonrpc": "2.0", "result": [], "server": "http://127.0.0.1:55742"}
# nethermind
{"id": 1, "jsonrpc": "2.0", "result": [], "server": "http://127.0.0.1:57012"}
# reth
{"error": {"code": -32603, "message": "unimplemented"}, "id": 1, "jsonrpc": "2.0", "server": "http://127.0.0.1:56156"}
```
#### debug_getRawBlock
When a block cannot be found, `geth` returns `0x`, whereas the other three clients return an error. Among those, `besu` returns a different error code (`32000`), while the others return `32001`.
```json
# geth
{"id": 1, "jsonrpc": "2.0", "result": "0x", "server": "http://127.0.0.1:56406"}
# besu
{"error": {"code": -32000, "message": "Block not found"}, "id": 1, "jsonrpc": "2.0", "server": "http://127.0.0.1:55742"}
# nethermind
{"error": {"code": -32001, "message": "Block BlockNumber, 3277422 was not found"}, "id": 1, "jsonrpc": "2.0", "server": "http://127.0.0.1:57012"}
# reth
{"error": {"code": -32001, "message": "block not found: 0x32026e"}, "id": 1, "jsonrpc": "2.0", "server": "http://127.0.0.1:56156"}
```
#### debug_getRawHeader
If the raw block cannot be found, `geth` and `reth` return an empty `0x`, while `besu` and `nethermind` return an error—but with different error codes.
```json
# geth
{"id": 1, "jsonrpc": "2.0", "result": "0x", "server": "http://127.0.0.1:56406"}
# besu
{"error": {"code": -32000, "message": "Block not found"}, "id": 1, "jsonrpc": "2.0", "server": "http://127.0.0.1:55742"}
# nethermind
{"error": {"code": -32001, "message": "Block BlockNumber, 3277422 was not found"}, "id": 1, "jsonrpc": "2.0", "server": "http://127.0.0.1:57012"}
# reth
{"id": 1, "jsonrpc": "2.0", "result": "0x", "server": "http://127.0.0.1:56156"}
```
#### debug_getRawReceipts
If the block cannot be found, `geth` returns `null`, `reth` returns an empty `[]`, while `besu` and `nethermind` return an error—with different error codes.
```json
# geth
{"id": 1, "jsonrpc": "2.0", "result": null, "server": "http://127.0.0.1:56406"}
# besu
{"error": {"code": -32000, "message": "Block not found"}, "id": 1, "jsonrpc": "2.0", "server": "http://127.0.0.1:55742"}
# nethermind
{"error": {"code": -32603, "data": "System.IO.InvalidDataException: Block 3277422 could not be found\n at Nethermind.JsonRpc.Modules.DebugModule.DebugBridge.GetReceiptsForBlock(BlockParameter blockParam) in /src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs:line 121\n at Nethermind.JsonRpc.Modules.DebugModule.DebugRpcModule.debug_getRawReceipts(BlockParameter blockParameter) in /src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs:line 337\n at System.Reflection.MethodInvoker.InvokeImpl(Object obj, Object arg1, Object arg2, Object arg3, Object arg4)\n at System.Reflection.MethodInvoker.Invoke(Object obj, Span`1 arguments)\n at Nethermind.JsonRpc.JsonRpcService.ExecuteAsync(JsonRpcRequest request, String methodName, ResolvedMethodInfo method, JsonRpcContext context) in /src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs:line 175", "message": "Internal error"}, "id": 1, "jsonrpc": "2.0", "server": "http://127.0.0.1:57012"}
# reth
{"id": 1, "jsonrpc": "2.0", "result": [], "server": "http://127.0.0.1:56156"}
```
#### debug_getRawTransaction
For `debug_getRawTransaction`, if the transaction cannot be found, `geth` returns `0x`, `besu` and `reth` return `null`, while `nethermind` returns an error.
```json
# geth
{"id": 1, "jsonrpc": "2.0", "result": "0x", "server": "http://127.0.0.1:56406"}
# besu
{"id": 1, "jsonrpc": "2.0", "result": null, "server": "http://127.0.0.1:55742"}
# nethermind
{"error": {"code": -32001, "message": "Transaction 0x3a2fd1a5ea9ffee477f449be53a49398533d2c006a5815023920d1c397298df3 was not found"}, "id": 1, "jsonrpc": "2.0", "server": "http://127.0.0.1:57012"}
# reth
{"id": 1, "jsonrpc": "2.0", "result": null, "server": "http://127.0.0.1:56156"}
```
Contributor guide
Assessment
This issue has not been assessed yet.