diff --git a/evm/evm-rpc/src/rpc-client.ts b/evm/evm-rpc/src/rpc-client.ts index b2ef8aff3..e7134436a 100644 --- a/evm/evm-rpc/src/rpc-client.ts +++ b/evm/evm-rpc/src/rpc-client.ts @@ -29,6 +29,9 @@ export class EvmRpcClient extends RpcClient { if (this.isRpcRateLimitError(err)) { return true } + if (this.isUpstreamUnavailableError(err)) { + return true + } if (this.isRpcInternalError(err)) { return this.retryInternalServerErrors } @@ -49,6 +52,18 @@ export class EvmRpcClient extends RpcClient { ) } + isUpstreamUnavailableError(err: RpcError): boolean { + // Load-balancing / aggregating providers (e.g. uniblock) report a transient + // "service unavailable" error when all of their upstream providers momentarily + // fail to fulfill a request. This is an availability problem (the HTTP 503 + // analog), not a permanent one, so it must be retried rather than crash the + // ingestion process. + return ( + err.code === -32503 || // JSON-RPC "service unavailable" code used by aggregating providers + /prevented the request from being fulfilled/i.test(err.message) + ) + } + isRpcRateLimitError(err: RpcError): boolean { return ( /rate limit|too many requests/i.test(err.message) ||