{"record":{"id":"97a383fca89fdd7b","repo":"risingwavelabs/risingwave","slug":"compact-with-plan-returned-no-result-for-a-non-emp","errorCode":null,"errorMessage":"compact_with_plan returned no result for a non-empty iceberg compaction plan","messagePattern":"compact_with_plan returned no result for a non-empty iceberg compaction plan","errorType":"exception","errorClass":"HummockError","httpStatus":null,"severity":"error","filePath":"src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs","lineNumber":512,"sourceCode":"                .await\n                .map_err(|e| HummockError::compaction_executor(e.as_report()))?;\n\n            let pk_index_result = build_pk_index_compaction_result(\n                &table,\n                data_files,\n                pk_index_input_file_paths,\n                pk_index_read_snapshot_id,\n            )?;\n\n            return Ok((stats, Some(pk_index_result)));\n        }\n\n        let compaction_result = compaction\n            .compact_with_plan(compaction_plan, &compaction_execution_config)\n            .await\n            .map_err(|e| HummockError::compaction_executor(e.as_report()))?\n            .ok_or_else(|| {\n                HummockError::compaction_executor(anyhow::anyhow!(\n                    \"compact_with_plan returned no result for a non-empty iceberg compaction plan\"\n                ))\n            })?;\n\n        let CompactionResult {\n            data_files,\n            stats,\n            table,\n        } = compaction_result;\n\n        if let (Some(committed_table), Some(cow_publish_plan)) = (table, cow_publish_plan) {\n            publish_cow_snapshot_to_main(\n                task_id,\n                &compaction,\n                &committed_table,\n                &branch,\n                &cow_publish_plan,\n                data_files,","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs#L494-L530","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Retry the compaction task — if transient, a fresh plan will be produced by meta.","Check compactor logs just before the error for evidence of dropped file groups or canceled rewrites (cancellation, file-not-found during rewrite).","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.","If reproducible with a consistent plan, this is an internal invariant violation — report with logs and the compaction plan."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match compaction.compact_with_plan(plan, &exec_cfg).await {\n    Ok(Some(result)) => commit(result),\n    Ok(None) if plan.file_group.data_files.is_empty() => Ok(Drained),\n    Ok(None) => { tracing::error!(\"invariant: empty result for non-empty plan\"); Err(invariant_violation()) }\n    Err(e) => Err(e),\n}","preventionTips":["Avoid running concurrent snapshot-expiry while COW compaction is publishing.","Monitor for frequent occurrences — each one is an internal invariant break worth a bug report.","Keep compactor and iceberg engine library versions consistent across nodes."],"tags":["rust","iceberg","compaction","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}