risingwavelabs/risingwave · error · HummockError

bounded compaction branch {branch} has no snapshot

Error message

bounded compaction branch {branch} has no snapshot

What it means

For bounded compaction the runner resolves the head snapshot of the target branch to validate the requested max_file_sequence_number boundary. If snapshot_for_ref(&branch) returns None — the branch has no snapshot (empty branch / never committed) — the boundary cannot be validated and the task fails closed.

Source

Thrown at src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs:967

    }

    let branch = commit_branch(iceberg_config.r#type.as_str(), iceberg_config.write_mode);

    let table = catalog
        .load_table(&table_ident)
        .await
        .map_err(|e| HummockError::compaction_executor(e.as_report()))?;

    if let Some(boundary) = max_file_sequence_number {
        // An empty bounded plan is reported as `Drained`, so fail closed unless
        // the loaded branch can prove that this fixed boundary is meaningful.
        if table.metadata().format_version() < FormatVersion::V2 {
            return Err(HummockError::compaction_executor(anyhow::anyhow!(
                "bounded compaction requires Iceberg format V2 or V3"
            )));
        }
        let head = table.metadata().snapshot_for_ref(&branch).ok_or_else(|| {
            HummockError::compaction_executor(anyhow::anyhow!(
                "bounded compaction branch {branch} has no snapshot"
            ))
        })?;
        if head.sequence_number() < boundary {
            return Err(HummockError::compaction_executor(anyhow::anyhow!(
                "bounded compaction head sequence {} is older than boundary {}",
                head.sequence_number(),
                boundary
            )));
        }
    }

    let planning_config = build_task_planning_config(
        compaction_kind,
        &iceberg_config,
        &config,
        max_file_sequence_number,
    )?;

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Ensure the iceberg sink has written at least one commit (a snapshot) before issuing bounded compaction; run a normal (unbounded) compaction or write data first.
  2. Verify the branch name resolved from the table config/write mode is the branch actually holding commits.
  3. Drop the max_file_sequence_number boundary and use the default unbounded compaction task.
  4. Check with an Iceberg reader (e.g. Spark) that snapshots.current-snapshot-id is not -1/null for this branch.

Example fix

// before
// bounded compaction request on a table with zero commits

// after: first commit data or run unbounded compaction
// compaction request without max_file_sequence_number
Defensive patterns

Strategy: validation

Validate before calling

fn branch_has_snapshot(table: &Table, branch: &str) -> bool {
    table.metadata().snapshot_for_ref(branch).is_some()
}

Prevention

When it happens

Trigger: create_task_execution with max_file_sequence_number set, and table.metadata().snapshot_for_ref(&branch) returns None because the branch (e.g. "main") has no head snapshot — the table/branch has no commits yet.

Common situations: Submitting bounded compaction to an empty or freshly created iceberg table/sink that has never committed a snapshot; pointing compaction at a branch name that exists but has never been committed to.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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