Skip to content

fix(claims): let a reindex recover a claim skipped by a ResolveError - #75

Merged
lucca65 merged 1 commit into
masterfrom
fix/claim-resolve-block-watermark
Sep 27, 2026
Merged

lucca65 merged 1 commit into
masterfrom
fix/claim-resolve-block-watermark

Conversation

@lucca65

@lucca65 lucca65 commented Sep 27, 2026

Copy link
Copy Markdown
Member

The bug

When resolveClaimId fails, claimAction throws a ResolveError. The ledgered wrapper then removes the action's _processed_actions row so that "a later reindex can pick it up". That reindex could never succeed. The watermark it searches above was the table-wide max(id). By the time anyone replays, that max sits above every claim in the replayed range, so the lookup starts above the skipped claim's id and throws again.

This happened in prod. Claim 20045 (action 115, created 2026-08-16 at block 427000148) was on chain and missing from the DB for six weeks. The anomaly check only flagged it on 2026-09-27, after the deploy, when it ran again. It was fixed that day by a one-row SQL insert with every value copied from the chain, because a reindex could not bring it back.

The fix

The watermark is now the highest claim id recorded at or before the action's block:

SELECT coalesce(max(id), 0) AS watermark FROM claims WHERE created_block <= $1

The chain.js comment on afterId is updated to match.

Verified on a local chain

One action, three claims in separate blocks: bob (id 1), carol (id 2), then bob again on the same action (id 3), which exercises the gap case. All three indexed with DB id = chain id. Then I recreated the prod state: deleted claim 1 and its _processed_actions row, which is what a ResolveError leaves behind. Then a full replay:

code claim 1 after replay log
master still missing resolveClaimId: no chain claim for action 1 / bob above id 3, skipped again
this branch restored: id 1, block 7135, correct proof; ledger row back 0 ResolveErrors, 51 already-processed actions skipped

Claim 3 (same action and claimer, later block) was untouched, and no duplicate rows appeared.

npx standard src/ passes. No deploy steps beyond the usual pull + pm2 restart event-source.

🤖 Generated with Claude Code

A claim skipped by a ResolveError could never come back through a reindex:
the resolver searched above the table-wide max claim id, which by replay time
sits above every claim being revisited, so the lookup threw again. Bound the
watermark by created_block <= the action's block. Indexing live this is the
same number as before; on replay it is where the watermark stood when the
claim was first seen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lucca65
lucca65 merged commit e3cf6ec into master Sep 27, 2026
2 checks passed
@lucca65
lucca65 deleted the fix/claim-resolve-block-watermark branch September 27, 2026 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant