ingest::chainlink::eth_call_result made its eth_call HTTP request with no timeout, so the backtest_run on-chain Chainlink round-walk hung indefinitely on the free publicnode RPC. Fixed on the analysis worktree with a 12s timeout + 4 retries with backoff. Worth upstreaming to main — it makes any harness Chainlink walk reliable.

For Agents — the fix

  • Symptom: backtest_run’s on-chain Chainlink round-walk hangs forever on the free publicnode RPC.
  • Cause: ingest::chainlink::eth_call_result had no reqwest timeout → a stalled/slow RPC response blocks with no deadline.
  • Fix (analysis worktree): add a reqwest 12s timeout + 4 retries with backoff to eth_call_result. Upstream to main so production/harness Chainlink reads share the hardening.
  • Next optimization (not yet done): the walk uses a fresh client per call (no connection reuse) → slow for long ranges; add connection pooling if long backtests are needed.

Symptoms

The backtest_run on-chain Chainlink round-walk (settlement label reconstruction) HUNG indefinitely on the free publicnode RPC — no progress, no error, no timeout.

Root cause

ingest::chainlink::eth_call_result issued the eth_call HTTP request with no reqwest timeout. A free public RPC that stalls (rate-limit, slow node, dropped connection) leaves the request with no deadline → the walk blocks forever on a single call.

Reusable gotcha

Any eth_call / RPC read against a free public RPC must carry an explicit HTTP timeout + retry. Production settlement uses the Alchemy POLYGON_RPC_URL (reliable); the harness walk used free publicnode, where the missing timeout surfaced. The timeout is correct hygiene regardless of RPC.

Fix (analysis worktree)

Added to eth_call_result:

  • reqwest 12s timeout — bounds each call so a stalled RPC can’t hang the walk.
  • 4 retries with backoff — rides out transient free-RPC failures.

Result: any harness Chainlink round-walk is now reliable. Worth upstreaming to main — it hardens both the production settlement read and every backtest that walks Chainlink rounds.

Known remaining slowness (next optimization)

The walk creates a fresh HTTP client per callno connection reuse. For long ranges this is slow (e.g. a week of BTC = too many sequential RPC calls, each paying fresh TLS/connection setup). Connection pooling (reuse a single reqwest::Client across the walk) is the next optimization if long-range backtests become a need. Not blocking today.