Skip to content

Fix/escrow pagination first zero - #1262

Open
nate-staked wants to merge 2 commits into
graphprotocol:mainfrom
nate-staked:fix/escrow-pagination-first-zero
Open

nate-staked wants to merge 2 commits into
graphprotocol:mainfrom
nate-staked:fix/escrow-pagination-first-zero

Conversation

@nate-staked

Copy link
Copy Markdown
Contributor

Problem

Since #1259 (v0.25.12), getEscrowAccounts pages paymentsEscrowAccounts and graphTallyTokensCollecteds with independent cursors, and sends first: 0 for whichever list finishes first. Graph Node only accepts 0 < first <= max_first (build_range), where max_first comes from GRAPH_GRAPHQL_MAX_FIRST and defaults to 1000. This check has been in Graph Node since at least v0.30.0. The follow-up page is therefore rejected with this error, whose wording is misleading because 0 isn't actually accepted.

We hit this on our canary right after upgrading to v0.25.12. It logged the following on every TAPv2 cycle (every 15 minutes) until we rolled back to v0.25.11:

[TAPv2] Failed to query pending RAVs
Error: Failed to query payments escrow accounts: [GraphQL] The `first` argument must be between 0 and 1000, but is 0
    at getEscrowAccounts (/opt/indexer/packages/indexer-common/dist/allocations/horizon-escrow-accounts.js:128:19)
    at async GraphTallyCollector.filterAndUpdateRavs (/opt/indexer/packages/indexer-common/dist/allocations/graph-tally-collector.js:304:32)

This affects any indexer with 1000+ graphTallyTokensCollecteds records, or 1000+ escrow accounts. For them, the escrow snapshot query fails every cycle and TAPv2 RAV redemption stops. Since the failure is logged at info, it's easy to miss.

Fix

  • Request first: 1 for a list that has finished. Its cursor is already past its last row at the pinned block, so the page comes back empty.
  • The test mock now enforces Graph Node's first range. Without the fix, four existing pagination tests fail with the production error.
  • Log the TAPv2 "Failed to query pending RAVs" and "Failed to reduce to signed RAVs" errors at error, matching TAPv1 in tap-collector.ts. This is a separate commit and easy to drop.

Testing

In packages/indexer-common, on Node 22: yarn format, yarn lint and yarn compile are clean, and jest src/allocations/__tests__/horizon-escrow-accounts.test.ts passes 14/14 (10/14 with only the mock change).

…tion

graphprotocol#1259 paginates paymentsEscrowAccounts and graphTallyTokensCollecteds with
independent cursors and sends `first: 0` for whichever list finishes first.
Graph Node only accepts 0 < first <= max_first (1000), so as soon as one
list outlives the other the follow-up page is rejected with "The `first`
argument must be between 0 and 1000, but is 0". getEscrowAccounts then
throws on every cycle, and TAPv2 RAV redemption stalls for any indexer
with 1000+ collected-token records.

Request a single row for a finished list instead. Its cursor is already
past its last row at the pinned block, so the page is empty.

The test mock now enforces Graph Node's `first` range; without the fix,
four existing pagination tests fail with the production error.
The TAPv2 pending-RAV query and RAV reduction pipelines reported failures
at info level, so a persistent failure (e.g. the escrow snapshot query
being rejected every cycle) was easy to miss. Log them at error level,
matching the equivalent TAPv1 handlers in tap-collector.ts.
@github-project-automation github-project-automation Bot moved this to 🗃️ Inbox in Indexer Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🗃️ Inbox

Development

Successfully merging this pull request may close these issues.

1 participant