linera-io/linera-protocol · error · ChainError
Checkpoint precondition failed: chain has consumed system ev
Error message
Checkpoint precondition failed: chain has consumed system events
What it means
check_checkpoint_preconditions (linera-chain/src/chain.rs:1638-1656) runs when a block starts with a Checkpoint operation: it scans next_expected_events and rejects the checkpoint if any stream belongs to the System application — i.e., the chain has pending, unconsumed system events (an active system event subscription whose next expected events have not arrived and been processed). Checkpointing requires that system event state to be clean first.
Source
Thrown at linera-chain/src/chain.rs:1650
/// no *system* event stream tracker is set.
///
/// The structural invariant that `Checkpoint` must be the *first* transaction in its
/// block is enforced unconditionally in `execute_block`, independently of these
/// preconditions. Sender-side event conditions are validated inside
/// `ExecutionStateView::prepare_checkpoint`.
async fn check_checkpoint_preconditions(&self) -> Result<(), ChainError> {
let mut had_system_event_tracker = false;
self.next_expected_events
.for_each_index_while(|stream_id| {
if matches!(stream_id.application_id, GenericApplicationId::System) {
had_system_event_tracker = true;
Ok(false)
} else {
Ok(true)
}
})
.await?;
ensure!(
!had_system_event_tracker,
ChainError::CheckpointPreconditionFailed("chain has consumed system events")
);
Ok(())
}
/// Returns the hashes of all blocks we have at the given heights, in input order.
/// Unknown heights are skipped.
#[instrument(skip_all, fields(
chain_id = %self.chain_id(),
next_block_height = %self.tip_state.get().next_block_height,
))]
pub async fn block_hashes_for_heights(
&self,
heights: impl IntoIterator<Item = BlockHeight>,
) -> Result<Vec<CryptoHash>, ChainError> {
let heights = heights.into_iter().collect::<Vec<_>>();View on GitHub (pinned to 6c226ddcb3)
Solutions
- Let the pending system events be delivered and processed (confirm the blocks carrying them) before proposing the checkpoint
- Retry the checkpoint proposal after the event stream quiets down — the condition is state-based and clears itself
- If the subscription is no longer needed, stop it so no new system events are expected
Example fix
// before: proposing the checkpoint immediately
client.submit_block(vec![checkpoint_tx]).await?; // CheckpointPreconditionFailed
// after: drain system events, then checkpoint (with retry)
loop {
client.process_system_events(chain_id).await?; // deliver + confirm pending events
match client.submit_block(vec![checkpoint_tx.clone()]).await {
Ok(_) => break,
Err(ChainError::CheckpointPreconditionFailed(_)) => continue,
Err(e) => return Err(e.into()),
}
} Defensive patterns
Strategy: try-catch
Try / catch
match client.submit_block(checkpoint_block).await {
Err(ChainError::CheckpointPreconditionFailed("chain has consumed system events")) => {
// pending system events exist: deliver and confirm them, then retry the
// same checkpoint proposal (the condition clears once streams are drained)
}
other => other?,
} Prevention
- Run checkpoints when system event streams are quiet, not right after subscribing
- Deliver pending system events before proposing checkpoint blocks
- Schedule checkpoint retries — the precondition is state-based and resolves itself
When it happens
Trigger: Proposing a Checkpoint block right after subscribing to system event streams, before the subscribed events were delivered and consumed; a checkpoint automation racing event-stream updates on the same chain.
Common situations: Checkpoint/backup tooling that snapshots chains on a timer while event subscriptions are active; chains used as event relays where system stream traffic is frequent, so the window of 'no pending system events' is narrow.
Related errors
- Checkpoint precondition failed: Checkpoint must be the first
- Events not found: {0:?}
- StreamNameTooLong
- Failed to deserialize event
- Default wallet directory is not supported in this platform:
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/3b709869b088f7dd.
Report an issue: GitHub.