risingwavelabs/risingwave · error · HummockError

compact_with_plan returned no result for a non-empty iceberg

Error message

compact_with_plan returned no result for a non-empty iceberg compaction plan

What it means

After dispatching a non-empty compaction plan, the runner calls compact_with_plan and expects Option<CompactionResult>. For a non-empty plan the engine must always return Some; None means the compaction engine produced no result at all. Since this violates the runner's contract with the compaction engine, it is converted into a HummockError::compaction_executor and the task fails instead of committing partial state.

Source

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

                .await
                .map_err(|e| HummockError::compaction_executor(e.as_report()))?;

            let pk_index_result = build_pk_index_compaction_result(
                &table,
                data_files,
                pk_index_input_file_paths,
                pk_index_read_snapshot_id,
            )?;

            return Ok((stats, Some(pk_index_result)));
        }

        let compaction_result = compaction
            .compact_with_plan(compaction_plan, &compaction_execution_config)
            .await
            .map_err(|e| HummockError::compaction_executor(e.as_report()))?
            .ok_or_else(|| {
                HummockError::compaction_executor(anyhow::anyhow!(
                    "compact_with_plan returned no result for a non-empty iceberg compaction plan"
                ))
            })?;

        let CompactionResult {
            data_files,
            stats,
            table,
        } = compaction_result;

        if let (Some(committed_table), Some(cow_publish_plan)) = (table, cow_publish_plan) {
            publish_cow_snapshot_to_main(
                task_id,
                &compaction,
                &committed_table,
                &branch,
                &cow_publish_plan,
                data_files,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Retry the compaction task — if transient, a fresh plan will be produced by meta.
  2. Check compactor logs just before the error for evidence of dropped file groups or canceled rewrites (cancellation, file-not-found during rewrite).
  3. Verify the pinned snapshot still exists on the table (a concurrently expired snapshot can leave the plan empty); reduce snapshot expiry pressure or re-run.
  4. If reproducible with a consistent plan, this is an internal invariant violation — report with logs and the compaction plan.
Defensive patterns

Strategy: retry

Try / catch

match compaction.compact_with_plan(plan, &exec_cfg).await {
    Ok(Some(result)) => commit(result),
    Ok(None) if plan.file_group.data_files.is_empty() => Ok(Drained),
    Ok(None) => { tracing::error!("invariant: empty result for non-empty plan"); Err(invariant_violation()) }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: compact_with_plan resolves to Ok(None) even though compaction_plan contained file groups — an internal invariant break in the iceberg compaction engine (e.g. plan emptied between planning and execution without signalling Drained).

Common situations: Race or bug where all planned file groups became ineligible mid-execution but the engine returned None instead of an empty/drain result; concurrency bugs in the rewrite executor; upgrading iceberg-rust library versions that changed empty-result semantics.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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