Problem
EngineRpc::rpc_request (crates/eth-engine/src/rpc/engine_rpc.rs) mints the JWT once, before the request is sent, and RpcRequestBuilder::send reuses that one token on every retry attempt. exchange_capabilities retries with ENGINE_EXCHANGE_CAPABILITIES_RETRY_RPC — a constant 3s delay and without_max_times(), so it never gives up.
The Engine API rejects a JWT whose iat is more than 60 seconds from the server clock (JWT_MAX_IAT_DIFF in alloy-rpc-types-engine, which is what reth's JwtAuthValidator checks). So if the execution client's auth port takes longer than a minute to come up, the consensus node keeps resending a token the EL can no longer accept, and no further retrying recovers it — the node stays locked out even after the EL is healthy, until restarted.
Two attempts 1.1s apart on main carry the byte-identical token (same {"iat":...} payload).
Proposed fix
Have the builder take the Auth instead of a finished token and mint one per attempt. Only EngineRpc sets it; the IPC transport carries no JWT and every other Engine method uses NoRetry, so nothing else changes. I have a patch with a wiremock test (fails on main, passes with the fix) ready to submit once assigned.
Problem
EngineRpc::rpc_request(crates/eth-engine/src/rpc/engine_rpc.rs) mints the JWT once, before the request is sent, andRpcRequestBuilder::sendreuses that one token on every retry attempt.exchange_capabilitiesretries withENGINE_EXCHANGE_CAPABILITIES_RETRY_RPC— a constant 3s delay andwithout_max_times(), so it never gives up.The Engine API rejects a JWT whose
iatis more than 60 seconds from the server clock (JWT_MAX_IAT_DIFFinalloy-rpc-types-engine, which is what reth'sJwtAuthValidatorchecks). So if the execution client's auth port takes longer than a minute to come up, the consensus node keeps resending a token the EL can no longer accept, and no further retrying recovers it — the node stays locked out even after the EL is healthy, until restarted.Two attempts 1.1s apart on
maincarry the byte-identical token (same{"iat":...}payload).Proposed fix
Have the builder take the
Authinstead of a finished token and mint one per attempt. OnlyEngineRpcsets it; the IPC transport carries no JWT and every other Engine method usesNoRetry, so nothing else changes. I have a patch with awiremocktest (fails onmain, passes with the fix) ready to submit once assigned.