risingwavelabs/risingwave · error · MetaError
replace sink must not use snapshot backfill
Error message
replace sink must not use snapshot backfill
What it means
A sink replace (ReplaceSink) command attempted to replace an existing sink using a job type of SnapshotBackfill or BatchRefresh, which is unsupported for replacement. Sink replacement must be a plain sink job, so the applier bails out.
Source
Thrown at src/meta/src/barrier/checkpoint/state.rs:910
let resolved_split_assignment = resolve_source_splits(
&info,
&actors,
edges.actor_new_no_shuffle(),
&self.database_info,
)?;
let old_sink_job_id = info
.replace_sink
.as_ref()
.map(|old_sink_id| old_sink_id.as_job_id());
if old_sink_job_id.is_some()
&& matches!(
job_type,
CreateStreamingJobType::SnapshotBackfill { .. }
| CreateStreamingJobType::BatchRefresh(_)
)
{
bail!("replace sink must not use snapshot backfill");
}
// Pre-apply: add new job and fragments
let cdc_tracker = if let Some(splits) = &info.cdc_table_snapshot_splits {
let (fragment, _) =
parallel_cdc_table_backfill_fragment(info.stream_job_fragments.fragments())
.expect("should have parallel cdc fragment");
Some(CdcTableBackfillTracker::new(
fragment.fragment_id,
splits.clone(),
))
} else {
None
};
self.database_info
.pre_apply_new_job(info.streaming_job.id(), cdc_tracker);
self.database_info.pre_apply_new_fragments(
info.stream_job_fragmentsView on GitHub (pinned to 6469eb736d)
Solutions
- Replace the sink without snapshot backfill/batch refresh job type
- Drop the old sink and create the new one as a fresh job instead
- Remove backfill options from the replace statement
Example fix
-- before: replace with backfill ALTER SINK s AS ... WITH BACKFILL; -- after DROP SINK s; CREATE SINK s AS ... WITH BACKFILL;
Defensive patterns
Strategy: validation
Validate before calling
if is_replace_sink(job) && matches!(job.job_type, SnapshotBackfill{..} | BatchRefresh(_)) {
return Err("use DROP+CREATE for backfill sinks");
} Type guard
fn replace_allows_backfill(jt: &CreateStreamingJobType) -> bool {
!matches!(jt, CreateStreamingJobType::SnapshotBackfill{..} | CreateStreamingJobType::BatchRefresh(_))
} Prevention
- Never attach backfill options to replace-sink statements
- Use DROP + CREATE when backfill is needed for a sink
- Validate job type client-side before submitting replace
When it happens
Trigger: Applying a replace-sink command via handle_new_barrier where the new job's CreateStreamingJobType is SnapshotBackfill or BatchRefresh.
Common situations: User tries to recreate a sink with a backfill/snapshot clause while an existing sink is being replaced; tooling or migration scripts generate replace commands with backfill options.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- old sink job {} not found in barrier state
- should get metadata on checkpoint barrier
- `Delete` operation is not supported in `append_only` mode
- `UpdateDelete` operation is not supported in `append_only` m
- Unsupported sink schema change op in iceberg sink: {:?}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/ed79f0780a37886c.
Report an issue: GitHub.