Summary
A follower node (CL in --follow mode) can deadlock permanently when a batched sync fetch fails at the wrong moment. On a failed fetch, sync's sync_height is advanced past all heights in the failed range, but only the first height of the range is re-requested. If the range covered more than one height, the later height is never requested again. Consensus then waits forever at that height while sync fills all max_parallel_requests=5 slots with later blocks that can never be delivered, so no new requests are ever issued. The services stay active — the node just silently stops advancing.
Observed on v0.7.3 (built from source), Arc testnet, chain id 5042002. The node wedged at height 52893874 and sat stalled for ~18 hours until the CL was manually restarted (restart fully recovers it).
Environment
- arc-node v0.7.3, built from the release tag via
cargo install
- CL:
arc-node-consensus start ... --follow --follow.endpoint https://rpc.drpc.testnet.arc.network,... --execution-persistence-backpressure
- EL:
arc-node-execution node --chain arc-testnet --disable-discovery ... (IPC to CL)
- Ubuntu 22.04.5, EL/CL on the same host
Timeline (2026-07-21, UTC)
The node had been sync-following normally. Certificate not found (-32004) fetch failures are chronic in our logs and are normally harmless because the failed height gets re-requested — until this sequence:
05:08:00.949949 sync{tip=52893872 sync_height=52893873}: Requesting sync from peer range=52893873..=52893873 peer=1Ak9...
05:08:00.957722 WARN Fetch failed request_id=39161 error="Failed to fetch certificates: JSON-RPC error: code -32004: Certificate not found"
05:08:00.957760 sync{tip=52893872 sync_height=52893874}: Re-requesting values from peer request_id=39161 except=1Ak9...
05:08:01.185749 sync{tip=52893872 sync_height=52893873}: Requesting sync from peer range=52893873..=52893874 peer=1Ak9... <-- 2-height range
05:08:01.195753 WARN Fetch failed request_id=39162 error="... code -32004: Certificate not found"
05:08:01.195778 sync{tip=52893872 sync_height=52893875}: Re-requesting values from peer request_id=39162 except=1Ak9... <-- sync_height jumped PAST 52893874
05:08:01.195788 sync{tip=52893872 sync_height=52893875}: Requesting sync from peer range=52893873..=52893873 peer=1AWR... <-- only 52893873 re-requested
05:08:01.321114 ✅ Fetch completed, sending blocks to consensus request_id=39163 start_height=52893873 count=1
05:08:01.348720 consensus{height=52893873}: Decided round=0 height=52893873
05:08:01.362328 consensus{height=52893874}: Starting new height height=52893874
05:08:01.689196 sync{tip=52893873 sync_height=52893875}: Requesting sync from peer range=52893875..=52893875 ... <-- 52893874 never requested again
The failed request 39162 covered 52893873..=52893874. Its failure bumped sync_height to 52893875, but the retry (39163) only covered 52893873..=52893873. Height 52893874 fell through the gap.
Sync then fetched 52893875–52893879 into its 5 parallel slots. Consensus can't decide 52893874 (no value, and as a follower with role=None it can't propose), those 5 pending deliveries never complete, and sync refuses to issue new requests:
05:08:04.364143 consensus{height=52893874 round=0}: Timeout elapsed step=Propose
05:08:06.364464 consensus{height=52893874 round=0}: Timeout elapsed step=Rebroadcast (repeats forever)
...
22:52:21.033505 sync{tip_height=52893873 sync_height=52893880}: SYNC REQUIRED: Falling behind tip_height=52893873 sync_height=52893880 peer_height=52987354
22:52:21.033517 sync{...}: Maximum number of parallel requests reached, skipping request for values max_parallel_requests=5 pending_requests=5
Meanwhile the EL just waits (its view of the incident):
22:47:11 WARN Beacon client online, but no consensus updates received for a while. ... period=63549.767870051s
Expected behavior
Either (a) a failed range fetch re-requests the entire failed range, not just its first height, or (b) sync detects tip_height + 1 < min(pending heights) and re-requests the gap, or (c) pending requests time out and free their slots so the gap can eventually be re-fetched. Any of these would prevent the permanent wedge.
Possibly related
During the same session (but ~2h earlier, and recovered automatically via the serial fallback) the EL hit a panic in the parallel state root task on v0.7.3:
thread 'tokio-rt' (1593146) panicked at .../reth-e231042ee7db3fb7/d6324d6/crates/trie/sparse/src/parallel.rs:3049:36:
node at path Nibbles(0x71) does not exist
02:50:17.736866 WARN Failed to compute state root in parallel
Happy to provide fuller logs for either issue.
Summary
A follower node (CL in
--followmode) can deadlock permanently when a batched sync fetch fails at the wrong moment. On a failed fetch, sync'ssync_heightis advanced past all heights in the failed range, but only the first height of the range is re-requested. If the range covered more than one height, the later height is never requested again. Consensus then waits forever at that height while sync fills allmax_parallel_requests=5slots with later blocks that can never be delivered, so no new requests are ever issued. The services stayactive— the node just silently stops advancing.Observed on v0.7.3 (built from source), Arc testnet, chain id 5042002. The node wedged at height 52893874 and sat stalled for ~18 hours until the CL was manually restarted (restart fully recovers it).
Environment
cargo installarc-node-consensus start ... --follow --follow.endpoint https://rpc.drpc.testnet.arc.network,... --execution-persistence-backpressurearc-node-execution node --chain arc-testnet --disable-discovery ...(IPC to CL)Timeline (2026-07-21, UTC)
The node had been sync-following normally.
Certificate not found(-32004) fetch failures are chronic in our logs and are normally harmless because the failed height gets re-requested — until this sequence:The failed request 39162 covered
52893873..=52893874. Its failure bumpedsync_heightto 52893875, but the retry (39163) only covered52893873..=52893873. Height 52893874 fell through the gap.Sync then fetched 52893875–52893879 into its 5 parallel slots. Consensus can't decide 52893874 (no value, and as a follower with
role=Noneit can't propose), those 5 pending deliveries never complete, and sync refuses to issue new requests:Meanwhile the EL just waits (its view of the incident):
Expected behavior
Either (a) a failed range fetch re-requests the entire failed range, not just its first height, or (b) sync detects
tip_height + 1 < min(pending heights)and re-requests the gap, or (c) pending requests time out and free their slots so the gap can eventually be re-fetched. Any of these would prevent the permanent wedge.Possibly related
During the same session (but ~2h earlier, and recovered automatically via the serial fallback) the EL hit a panic in the parallel state root task on v0.7.3:
Happy to provide fuller logs for either issue.