Summary
multidownloader does not recognise explicit eth_getLogs block-range cap errors, so such an error propagates out of its shrink logic and the surrounding infinite retry loop re-issues the same oversized range forever. It already defaults to BlockChunkSize = 10000 (config/default.go:429), so a range-capped RPC provider can wedge an L1/L2 multidownloader today.
Detail
isEthClientErrorTooManyResults (multidownloader/evm_multidownloader.go:879) only matches "too many results"-style responses. On a match, requestLogs shrinks via currentSyncBlockChunkSize /= chunkSizeReductionFactor (10), floored at minChunkSize (:1012-1013). Any error that is instead an explicit range cap — e.g. block range too large, max range: N, exceeded maximum block range: N, eth_getLogs is limited to a N range, query exceeds max block range N — fails the check at :997, is returned as a hard error, and the chunk size is never reduced. With MaxRetryAttemptsAfterError = -1 the same query is retried indefinitely.
Those four shapes are already parsed by aggkitcommon.ParseMaxRangeFromError (common/errors.go), which multidownloader does not use.
Context
PR for #1842 consolidated every other eth_getLogs size/range handler into a single shared decision point, aggkitcommon.NextEthGetLogsWindow (common/errors.go), and wired it into:
sync/evmdownloader.go (shared by BridgeL1Sync, BridgeL2Sync, ClaimL1Sync, ClaimL2Sync, L1InfoTreeSync legacy, L2GERSync main loops)
claimsync/claimsync.go (settled-IBE RPC scan)
l2gersync/l2_evm_ger_reader.go and l2gersync/evm_downloader_sovereign.go
multidownloader was deliberately left out of that change because fixing it means editing a retry loop coupled to its own batching, partial-availability and reorg-check logic, which warrants a dedicated test pass. It is not a regression from that PR — its BlockChunkSize = 10000 default predates it and was not modified.
Suggested fix
Teach multidownloader's fallback branch in requestLogs to consult aggkitcommon.NextEthGetLogsWindow(err, currentWindow) before giving up, so range-cap errors shrink to the reported cap instead of propagating. Keeping its existing chunkSizeReductionFactor / minChunkSize behaviour for the "too many results" family is fine; the goal is that no size/range error reaches the outer infinite retry loop unshrunk.
Acceptance
- A range-cap error causes the window to shrink and the scan to complete (red/green: prove it previously retried the same range indefinitely).
- An unrelated error still propagates unchanged.
- The shrink loop terminates at the minimum window.
Summary
multidownloaderdoes not recognise expliciteth_getLogsblock-range cap errors, so such an error propagates out of its shrink logic and the surrounding infinite retry loop re-issues the same oversized range forever. It already defaults toBlockChunkSize = 10000(config/default.go:429), so a range-capped RPC provider can wedge an L1/L2 multidownloader today.Detail
isEthClientErrorTooManyResults(multidownloader/evm_multidownloader.go:879) only matches "too many results"-style responses. On a match,requestLogsshrinks viacurrentSyncBlockChunkSize /= chunkSizeReductionFactor(10), floored atminChunkSize(:1012-1013). Any error that is instead an explicit range cap — e.g.block range too large, max range: N,exceeded maximum block range: N,eth_getLogs is limited to a N range,query exceeds max block range N— fails the check at:997, is returned as a hard error, and the chunk size is never reduced. WithMaxRetryAttemptsAfterError = -1the same query is retried indefinitely.Those four shapes are already parsed by
aggkitcommon.ParseMaxRangeFromError(common/errors.go), whichmultidownloaderdoes not use.Context
PR for #1842 consolidated every other
eth_getLogssize/range handler into a single shared decision point,aggkitcommon.NextEthGetLogsWindow(common/errors.go), and wired it into:sync/evmdownloader.go(shared by BridgeL1Sync, BridgeL2Sync, ClaimL1Sync, ClaimL2Sync, L1InfoTreeSync legacy, L2GERSync main loops)claimsync/claimsync.go(settled-IBE RPC scan)l2gersync/l2_evm_ger_reader.goandl2gersync/evm_downloader_sovereign.gomultidownloaderwas deliberately left out of that change because fixing it means editing a retry loop coupled to its own batching, partial-availability and reorg-check logic, which warrants a dedicated test pass. It is not a regression from that PR — itsBlockChunkSize = 10000default predates it and was not modified.Suggested fix
Teach
multidownloader's fallback branch inrequestLogsto consultaggkitcommon.NextEthGetLogsWindow(err, currentWindow)before giving up, so range-cap errors shrink to the reported cap instead of propagating. Keeping its existingchunkSizeReductionFactor/minChunkSizebehaviour for the "too many results" family is fine; the goal is that no size/range error reaches the outer infinite retry loop unshrunk.Acceptance