Skip to content

fix(empty_blocks_sanitizer): handle nil block result, flag for refetch#20

Merged
rymcol merged 1 commit intosignet-mainfrom
signet-main-with-fix
Apr 17, 2026
Merged

fix(empty_blocks_sanitizer): handle nil block result, flag for refetch#20
rymcol merged 1 commit intosignet-mainfrom
signet-main-with-fix

Conversation

@rswanson
Copy link
Copy Markdown
Member

Summary

  • Equivalent of master PR fix: handle nil block result in EmptyBlocksSanitizer #19, applied directly to `signet-main` so the `publish-init4-docker.yml` workflow rebuilds `ghcr.io/init4tech/blockscout:latest` with the fix.
  • `EmptyBlocksSanitizer.classify_blocks_from_result/1` crashes with `BadMapError` when the upstream RPC returns `result: null` (pruned or reorged blocks). Each crash trips `restart: :permanent` supervisor restart intensity, bringing down the `indexer` application and the whole BEAM VM → K8s crashloop.
  • Adds a `%{id: _, result: nil}` match clause that skips without crashing, plus caller-side reconciliation that flags the missing block numbers with `Block.set_refetch_needed/1` so they exit the sanitizer's query set (`consensus_blocks_with_nil_is_empty_query` filters on `refetch_needed == false`) and stop being re-queried every 10s.
  • Regression test mocks a nil batch response and uses `wait_for_results` to assert `refetch_needed == true`; the un-fixed code would crash and the assertion would time out.

Merge resolution notes

`signet-main` already had a defensive `Map.get(block, "transactions") || []` + `block_fields/2` signature for the case where `block` is a map but the `transactions` field is missing. That handles a different edge case than `result: nil`, so both guards are preserved in this patch.

Why this branch, not master

Master PR #19 was merged, but the daily `sync-upstream.yml` will `git reset --hard upstream/master` on init4tech/master and wipe that merge. `signet-main` is the deploy branch that actually triggers `publish-init4-docker.yml`, so the fix has to land here.

Test plan

  • CI: `Indexer Tests` passes the new `skips/marks nil block` test
  • Merge → `publish-init4-docker.yml` runs → arm64+amd64 build + `:latest` manifest push
  • Restart the blockscout pod; confirm it stops crashlooping

🤖 Generated with Claude Code

When the JSON-RPC returns \`result: null\` for a block (pruned, reorged
out, or genuinely missing), \`classify_blocks_from_result/1\` crashed
with \`BadMapError\` on \`Map.get(nil, "transactions", nil)\`. Because the
fetcher is \`restart: :permanent\`, each crash exhausted the supervisor's
restart intensity and brought down the \`indexer\` application + BEAM VM,
producing a K8s crashloop against Signet's sidecar RPC.

- Add a \`%{id: _, result: nil}\` match clause that skips without
  crashing.
- Reconcile requested vs. returned block numbers in the caller and
  flag the missing ones with \`Block.set_refetch_needed/1\` so
  \`consensus_blocks_with_nil_is_empty_query\` stops re-selecting them
  every cycle.
- Regression test stubs a nil batch response and uses
  \`wait_for_results\` to assert \`refetch_needed == true\`; on the
  un-fixed code the GenServer crashes and the assertion times out.

Merged equivalent of master PR #19 onto signet-main. Preserves the
existing defensive \`Map.get(block, "transactions") || []\` guard from
this branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rswanson rswanson requested a review from a team April 17, 2026 00:03
@rymcol rymcol merged commit 064319d into signet-main Apr 17, 2026
1 check passed
@rymcol rymcol deleted the signet-main-with-fix branch April 17, 2026 00:05
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.

2 participants