Two failures that go away when the same call is repeated are still classified as permanent, so the dump exits and restarts instead of retrying. #584 did not cover either.
1. HTTP 500 with a non-JSON body
A provider's edge answers some calls with
HTTP/1.1 500
content-type: text/plain;charset=UTF-8
Uncaught exception
The same call succeeds after the restart.
EvmRpcClient.isConnectionError retries a 500 only under retryInternalServerErrors, or when the body holds JSON-RPC errors that are all transient. A plain-text body yields no errors, so the 500 is fatal.
RpcClient.isConnectionError, which bitcoin-dump and the other non-EVM dumps use, never retries a 500.
A 500 has to stay fatal in general: Bitcoin Core, for one, answers ordinary JSON-RPC errors with HTTP 500 and a JSON body. A 500 whose body is not a JSON-RPC response, though, is not the node's answer to the request but the proxy in front of it failing.
Proposal: in RpcClient.isConnectionError, treat a 500 whose body is not a JSON-RPC response as a connection error.
2. Execution error while tracing a block that is already on chain
debug_traceBlockByHash (callTracer) on a canonical block failed with
tracing failed: insufficient funds for gas * price + value: address 0x… have 0 want …
The node's code was -32000; a proxy in front of it passed it on as -32003 with the cause ErrEndpointExecutionException. A transaction included in a block passed these checks when it was mined, so this answer to a trace call means the node that served it has wrong state for that block. After the restart the same call succeeded.
isTransientError lists ErrEndpointExecutionException as permanent. That is right for eth_call or eth_estimateGas, where the request itself fails, but not for debug_trace* or trace_* on a mined block. retryInternalServerErrors does not help either, since -32003 is not one of the internal codes.
Proposal: for trace methods, retry transaction pre-check failures (insufficient funds for gas, nonce too low / nonce too high, intrinsic gas too low) whatever code or proxy cause they come under.
Trade-off
The dumper retries without limit, so a failure misjudged as transient shows up as a dump that stops advancing rather than one that restarts. For these two shapes the call has succeeded on every repeat so far.
Two failures that go away when the same call is repeated are still classified as permanent, so the dump exits and restarts instead of retrying. #584 did not cover either.
1. HTTP 500 with a non-JSON body
A provider's edge answers some calls with
The same call succeeds after the restart.
EvmRpcClient.isConnectionErrorretries a 500 only underretryInternalServerErrors, or when the body holds JSON-RPC errors that are all transient. A plain-text body yields no errors, so the 500 is fatal.RpcClient.isConnectionError, which bitcoin-dump and the other non-EVM dumps use, never retries a 500.A 500 has to stay fatal in general: Bitcoin Core, for one, answers ordinary JSON-RPC errors with HTTP 500 and a JSON body. A 500 whose body is not a JSON-RPC response, though, is not the node's answer to the request but the proxy in front of it failing.
Proposal: in
RpcClient.isConnectionError, treat a 500 whose body is not a JSON-RPC response as a connection error.2. Execution error while tracing a block that is already on chain
debug_traceBlockByHash(callTracer) on a canonical block failed withThe node's code was -32000; a proxy in front of it passed it on as -32003 with the cause
ErrEndpointExecutionException. A transaction included in a block passed these checks when it was mined, so this answer to a trace call means the node that served it has wrong state for that block. After the restart the same call succeeded.isTransientErrorlistsErrEndpointExecutionExceptionas permanent. That is right foreth_calloreth_estimateGas, where the request itself fails, but not fordebug_trace*ortrace_*on a mined block.retryInternalServerErrorsdoes not help either, since -32003 is not one of the internal codes.Proposal: for trace methods, retry transaction pre-check failures (
insufficient funds for gas,nonce too low/nonce too high,intrinsic gas too low) whatever code or proxy cause they come under.Trade-off
The dumper retries without limit, so a failure misjudged as transient shows up as a dump that stops advancing rather than one that restarts. For these two shapes the call has succeeded on every repeat so far.