linera-io/linera-protocol · error · ExecutionError

CheckpointPreconditionFailed

CheckpointPreconditionFailed

Error message

ExecutionError::CheckpointPreconditionFailed("chain has published system events")

What it means

prepare_checkpoint validates a SystemOperation::Checkpoint before dumping chain state: it walks previous_event_blocks and refuses to checkpoint if any event stream in it belongs to the System application (e.g. the epoch stream published by the admin chain). User event streams are summarized and pruned by the checkpoint itself, but system event streams are not, so checkpointing would lose them; the operation fails with CheckpointPreconditionFailed.

Source

Thrown at linera-execution/src/execution.rs:146

        &mut self,
        maximum_blob_size: u64,
    ) -> Result<Vec<Blob>, ExecutionError> {
        // User event streams are summarized and pruned by the checkpoint itself (see
        // `ExecutionStateActor`'s checkpoint handler), so they do not block checkpointing.
        // System event streams (e.g. the epoch streams on the admin chain) are not
        // summarized, so a chain that published any is still not allowed to checkpoint.
        let mut had_system_event_block = false;
        self.previous_event_blocks
            .for_each_index_while(|stream_id| {
                if matches!(stream_id.application_id, GenericApplicationId::System) {
                    had_system_event_block = true;
                    Ok(false)
                } else {
                    Ok(true)
                }
            })
            .await?;
        ensure!(
            !had_system_event_block,
            ExecutionError::CheckpointPreconditionFailed("chain has published system events")
        );

        let (bytes, _content_hash) = self.inner.dump_content().await?;
        let chunk_size = usize::try_from(maximum_blob_size).unwrap_or(usize::MAX);
        Ok(bytes
            .chunks(chunk_size)
            .map(|chunk| {
                Blob::new(BlobContent::new(
                    BlobType::CheckpointExecutionState,
                    chunk.to_vec(),
                ))
            })
            .collect())
    }

    /// Registers the pre-block-computed checkpoint inputs (from

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Run the checkpoint from a chain that has never published system events (not the admin chain)
  2. Keep epoch and committee administration isolated on the admin chain and checkpoint only application chains
  3. Before proposing a checkpoint, verify the chain's event streams contain no GenericApplicationId::System entries
Defensive patterns

Strategy: try-catch

Type guard

fn is_checkpoint_precondition_failed(err: &ExecutionError) -> bool {
    matches!(err, ExecutionError::CheckpointPreconditionFailed(_))
}

Try / catch

match state.prepare_checkpoint(max_blob_size).await {
    Ok(blobs) => blobs,
    Err(ref e) if is_checkpoint_precondition_failed(e) => {
        // chain state makes it ineligible; do not retry on this chain
        return Err(anyhow!("this chain has published system events and cannot checkpoint"));
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Executing SystemOperation::Checkpoint on a chain that has ever published system events, typically the admin chain, which publishes EPOCH_STREAM_NAME events whenever a committee or epoch is created.

Common situations: Trying to checkpoint the admin chain itself; chains that combine system duties (epoch/committee publication) with application load; test chains reused for both epoch publication and checkpoint tests; node upgrades where checkpoint eligibility rules were tightened.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/e83836e3c003fa4a. Report an issue: GitHub.