risingwavelabs/risingwave · error · StreamExecutorError

iceberg pk-index merger {} received a non-checkpoint compact

Error message

iceberg pk-index merger {} received a non-checkpoint compaction resume barrier {:?}

What it means

The iceberg pk-index merger only allows a barrier that resumes a paused compaction task (iceberg_pk_index_compaction resume) to arrive at a checkpoint barrier, because resume must align with a persistent epoch boundary. If a barrier carries a compaction resume task id but is not a checkpoint, execute_inner aborts with this error. Resuming on a non-checkpoint barrier would break recovery invariants.

Source

Thrown at src/stream/src/executor/iceberg_with_pk_index/position_delete_merger.rs:130

                        debug_assert_eq!(op, risingwave_common::array::Op::Insert);
                        let file_path = row
                            .datum_at(0)
                            .map(|d| d.into_utf8())
                            .context("file_path should not be null")?;
                        let position = row
                            .datum_at(1)
                            .context("position should not be null")?
                            .into_int64();
                        self.handler
                            .write(file_path, position)
                            .map_err(|e| StreamExecutorError::sink_error(e, self.sink_id))?;
                    }
                }
                Message::Barrier(barrier) => {
                    barrier.assume_no_update_vnode_bitmap(self.actor_id)?;
                    let compaction_resumed = self.compaction_resume_task_id(&barrier);
                    if compaction_resumed.is_some() && !barrier.is_checkpoint() {
                        bail!(
                            "iceberg pk-index merger {} received a non-checkpoint compaction resume barrier {:?}",
                            self.sink_id,
                            barrier.epoch
                        );
                    }

                    let mut metadata = None;
                    if barrier.is_checkpoint() {
                        metadata = self
                            .handler
                            .flush()
                            .await
                            .map_err(|e| StreamExecutorError::sink_error(e, self.sink_id))?;
                    }

                    if let Some(metadata) = metadata
                        && metadata.metadata.is_some()
                    {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check the compaction scheduler on the meta side to ensure resume mutations are only attached to checkpoint barriers.
  2. Align checkpoint interval so compaction resumes can be delivered at checkpoints.
  3. Verify meta/stream node version compatibility.
  4. Restart the fragment; this is an invariant violation and recovery should re-plan the compaction task.
  5. File a bug with the barrier details (epoch) if reproducible.
Defensive patterns

Strategy: validation

Validate before calling

// caller-side (meta/scheduler) invariant check before sending resume
if compaction_resume_pending && !barrier.is_checkpoint() {
    // defer the resume mutation to the next checkpoint barrier
}

Type guard

fn resume_is_legal(barrier: &Barrier, resume_task: Option<IcebergCompactionTaskId>) -> bool {
    resume_task.is_none() || barrier.is_checkpoint()
}

Try / catch

match res {
    Err(e) if e.to_string().contains("non-checkpoint compaction resume barrier") => {
        error!("compaction resume delivered off-checkpoint; restarting fragment from checkpoint");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Raised in execute_inner when self.compaction_resume_task_id(&barrier) returns Some while barrier.is_checkpoint() is false — the meta node issued a compaction-resume mutation attached to a non-checkpoint barrier.

Common situations: Meta scheduler bug issuing resume mutations on high-frequency non-checkpoint barriers; misconfigured checkpoint interval making resumes attach to the wrong barrier type; version skew between meta and stream nodes.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/c6a25dc6d5da605c. Report an issue: GitHub.