risingwavelabs/risingwave · warning
manual Full compaction is rejected while an automatic round…
Error message
manual Full compaction is rejected while an automatic round is active for sink {} What it means
This error comes from the Iceberg compaction scheduler in the RisingWave meta node when a manual Full compaction is requested via start_manual_compaction. The sink already has an automatic compaction round in progress (round_max_file_sequence_number is set), and running a manual Full compaction concurrently with it is not allowed. The request is rejected instead of being queued, so the caller must retry after the automatic round finishes.
Solutions
- Wait for the automatic compaction round to complete, then retry the manual Full compaction
- Check the sink's compaction state/progress (logs tagged iceberg_operation) before triggering manual compaction
- Adjust compaction_interval_sec / trigger_snapshot_count so automatic rounds are less likely to overlap with maintenance windows
- If stuck, cancel or wait for the automatic round via the sink lifecycle; note restarts of the meta node reset in-memory track state
Example fix
// before
manager.start_manual_compaction(sink_id).await?; // Err: auto round active
// after
if !manager.auto_round_active(&sink_id) {
manager.start_manual_compaction(sink_id).await?;
} else {
schedule_retry_after_auto_round(sink_id);
} Defensive patterns
Strategy: validation
Validate before calling
// Check track state before requesting manual compaction
fn can_request_manual_compaction(track: Option<&CompactionTrack>) -> bool {
track
.map(|t| t.round_max_file_sequence_number.is_none()
&& matches!(t.state, CompactionTrackState::Idle { .. }))
.unwrap_or(true)
} Type guard
fn is_auto_round_active(track: &CompactionTrack) -> bool {
track.round_max_file_sequence_number.is_some()
} Prevention
- Check the sink's compaction state before issuing manual Full compaction
- Schedule manual compaction outside automatic compaction windows
- Serialize admin compaction operations through a single operator/tool
- On rejection, back off and retry after the auto round completes rather than hammering the API
When it happens
Trigger: Calling start_manual_compaction (e.g. via a manual compaction API/SQL command) for a sink whose sink_schedules track has round_max_file_sequence_number set to Some, meaning an automatic compaction round is currently active.
Common situations: Operators triggering manual full compaction while periodic/automatic compaction (triggered by snapshot count or interval) is still running for the same Iceberg sink; racing another admin's manual trigger right after auto-compaction kicked off.
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
- iceberg compaction task is already running for sink
- iceberg compaction task is already running for sink
- manual iceberg compaction is already waiting for sink
- apply iceberg pk-index sink overwrite_files action
- bounded compaction is not supported for copy-on-write tasks
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/ee0867782ebbf47d.
Report an issue: GitHub.
Appendix: source
Thrown at src/meta/src/manager/iceberg_compaction/schedule.rs:918
SinkUpdateKind::ManualForceCompaction {
task_type: TaskType::Full,
},
Instant::now(),
)
.await;
let mut guard = self.inner.write();
let now = Instant::now();
if guard.manual_compaction_waiters.contains_key(&sink_id) {
return Err(anyhow!(
"manual iceberg compaction is already waiting for sink {}",
sink_id
)
.into());
}
if let Some(track) = guard.sink_schedules.get(&sink_id) {
if track.round_max_file_sequence_number.is_some() {
return Err(anyhow!(
"manual Full compaction is rejected while an automatic round is active for sink {}",
sink_id
)
.into());
}
match &track.state {
CompactionTrackState::PendingDispatch { attempt } => {
return Err(anyhow!(
"iceberg compaction task is already running for sink {} \
(state=pending_dispatch, pending_commit_count_at_start={}, \
pending_commit_count={})",
sink_id,
attempt.pending_commit_count_at_start,
track.pending_commit_count
)
.into());
}
CompactionTrackState::InFlight {View on GitHub (pinned to 6469eb736d)