fix(evm-rpc): retry eRPC upstreams-exhausted errors instead of crashing the dumper - #545
fix(evm-rpc): retry eRPC upstreams-exhausted errors instead of crashing the dumper#545elina-chertova wants to merge 1 commit into
Conversation
When routed through eRPC, a transient upstream failure (all providers
rate-limited or returning 5xx) comes back as an HTTP 200 JSON-RPC error
whose code can be normalized to a misleading value such as -32601
("method not found"). EvmRpcClient treated that as fatal, so a single
provider hiccup crash-looped the dumper. Recognize eRPC's stable
data.code (ErrUpstreamsExhausted / ErrFailsafeRetryExceeded) as a
retryable connection error, matching how a direct provider 5xx is
already retried.
|
Related open PRs harden |
|
Bumping this: the exact crash this PR fixes is currently firing fleet-wide — a correlated cluster of ~34 alerts across 19 Alchemy-primary EVM archive networks ( Confirmed against live pod logs that this PR's
One sibling variant I did not see a
Given the fleet-wide impact, could we get this reviewed/merged and rolled to the archive dumpers? Happy to add the soneium parse-variant if you'd like it in the same PR. |
Symptom
Alert linea-mainnet_No_Dumper_Data (evm-archive, kind=dump).
dump-linea-mainnet-0is in CrashLoopBackOff (140 restarts / 27h); no raw data written.Root cause (proven from pod logs)
The linea-mainnet dumper was routed through eRPC on 2026-07-22 (infra commit
248d45930"Roll out eRPC to almost every archive ingester"; the dump pod's 27h age matches). eRPC's only primary upstream for linea is Alchemy, which is currently degraded — live probes return HTTP 503-32001 "Unable to complete request at this time"and 429 "compute units per second exceeded" for linea.eRPC does not fail over to the healthy dwellir/uniblock fallbacks, and returns the request as an HTTP 200 body carrying a JSON-RPC error whose code is normalized to
-32601("method eth_getBlockByNumber does not exist/is not available") withdata.code: ErrFailsafeRetryExceeded→cause.code: ErrUpstreamsExhausted.EvmRpcClient.isConnectionErrordid not recognize this shape, so the error was fatal (dump log level 5) and the process exited:Before the eRPC switch the same underlying Alchemy 503 arrived as a raw HTTP 503, which the client already retries — so eRPC repackaging it as a fatal JSON-RPC error is what turned a recoverable degradation into a crash-loop.
Fix
Recognize eRPC's stable
data.code(ErrUpstreamsExhausted/ErrFailsafeRetryExceeded) as a retryable connection error inEvmRpcClient.isConnectionError. This restores parity with a direct provider 5xx: the dumper backs off and retries (retryAttempts=MAX) instead of crash-looping, so a single provider hiccup can no longer take the dump down. A genuine-32601with no eRPCdatastays fatal.Test
evm/evm-rpc/test/rpc-client.test.ts— asserts the production error shape is retryable and a real method-not-found is not. Red on pre-fix (2 fail), green after.Falsification
If the dump still crash-loops after deploying an evm-dump built from this change with the same
-32601/ErrUpstreamsExhaustedfatal line, the classifier isn't matching the real payload shape.Note (operator action, not in this PR)
This stops the crash-loop but does not by itself restore linea data flow: Alchemy is down for linea while eRPC isn't failing over. An operator should route linea to a healthy provider (dwellir + uniblock both return 200 for linea now) or fix the eRPC failover, and raise the Alchemy linea 503/429 with the provider (https://status.alchemy.com). Provider swaps are an operator mitigation, so they're intentionally not included here.