Skip to content

light-base: panic in Subscription::unpin_block — parachain sync double-unpins a relay block #3286

@lrubasze

Description

@lrubasze

Panic

panicked at light-base/src/runtime_service.rs:493:34:
called `Result::unwrap()` on an `Err` value: ()
  • Parachain sync asks the relay subscription to unpin an already-unpinned block → background returns Err(())Subscription::unpin_block unwraps it → panic.
  • Seen on a parachain network (Sentry DOTLI-7P, staging, paseo-next-v2, shared-worker; low frequency, 0 users impacted): https://paritytech.sentry.io/issues/119036335/

Root cause

  • sync_service/paraheads.rs unpins a relay block on two paths:
    • when its parahead fetch finishes,
    • when it's pruned, only if its pruned_blocks async-op data is_none().
  • AsyncTree::try_advance_output maps a pruned Finished { reported: false } block to None instead of Some(user_data) (the existing "TAsync thrown away silently / TODO" corner case in lib/src/chain/async_tree.rs).
  • Result: a relay block whose parahead finished but was never reported before being pruned hits both paths → unpinned twice → Err(()).

Trigger

  • Relay block's parahead fetch completes (unpinned on finish), then
  • block is pruned before being reported (e.g. on a fork that loses to finalization).
  • Timing/topology race against relay reorgs near finality → low frequency.

Reproduction

  • Deterministic at the AsyncTree layer: a finished-but-unreported pruned block comes back in OutputUpdate::Finalized.pruned_blocks with None, despite async_op_finished already returning it.

Suggested fix

  • In try_advance_output, return Some(user_data) for any Finished pruned block regardless of reported.
  • Only paraheads reads this value; runtime_service ignores it.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions