risingwavelabs/risingwave · error
upstream table id not covered: {}
Error message
upstream table id not covered: {} What it means
`fill_snapshot_backfill_epoch` looks up each snapshot-backfill StreamScan's table id in the collected SnapshotBackfillInfo maps (cross-db first, then regular). If the table id appears in neither map, the scan cannot receive a backfill epoch and the function errors, since leaving the epoch unset would produce an invalid graph.
Source
Thrown at src/meta/src/stream/stream_graph/fragment.rs:1622
let mut applied = false;
visit_stream_node_cont_mut(node, |node| {
if let Some(NodeBody::StreamScan(stream_scan)) = node.node_body.as_mut()
&& (stream_scan.stream_scan_type == StreamScanType::SnapshotBackfill as i32
|| stream_scan.stream_scan_type == StreamScanType::CrossDbSnapshotBackfill as i32)
{
result = try {
let table_id = stream_scan.table_id;
let snapshot_epoch = cross_db_snapshot_backfill_info
.upstream_mv_table_id_to_backfill_epoch
.get(&table_id)
.or_else(|| {
snapshot_backfill_info.and_then(|snapshot_backfill_info| {
snapshot_backfill_info
.upstream_mv_table_id_to_backfill_epoch
.get(&table_id)
})
})
.ok_or_else(|| anyhow!("upstream table id not covered: {}", table_id))?
.ok_or_else(|| anyhow!("upstream table id not set: {}", table_id))?;
if let Some(prev_snapshot_epoch) =
stream_scan.snapshot_backfill_epoch.replace(snapshot_epoch)
{
Err(anyhow!(
"snapshot backfill epoch set again: {} {} {}",
table_id,
prev_snapshot_epoch,
snapshot_epoch
))?;
}
applied = true;
};
result.is_ok()
} else {
true
}
});View on GitHub (pinned to 6469eb736d)
Solutions
- Ensure collect_snapshot_backfill_info_impl ran over all fragments containing the scan (fragment_type_mask includes the scan fragments).
- Verify the upstream MV's table id didn't change (e.g. after replace) and that maps were built with the same ids.
- Recreate the MV chain if the topology was mutated mid-flight, then retry.
Defensive patterns
Strategy: try-catch
Try / catch
// Check coverage before filling:
if !info.upstream_mv_table_id_to_backfill_epoch.contains_key(&table_id) {
// skip or collect first
} Prevention
- Always run collect_snapshot_backfill_info_impl over the full fragment set before fill.
- Verify table ids are stable across collect/fill phases (no concurrent replaces).
- Log the collected map contents when debugging backfill epoch failures.
When it happens
Trigger: Filling epochs during replace/refresh where a StreamScan node's table_id is missing from both `cross_db_snapshot_backfill_info` and `snapshot_backfill_info.upstream_mv_table_id_to_backfill_epoch` — e.g. the collect step skipped a fragment or the upstream relation changed id.
Common situations: Schema change or MV refresh where upstream MV topology changed between collect and fill; cross-database scans referencing MVs not registered in the info map; bugs in fragment collection.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- must be either all snapshot_backfill or no snapshot_backfill
- upstream table id not set: {}
- auto schema change with drop column only supports Project wi
- new column id not found in scan output
- Different number of internal tables. New: {}, Old: {}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/1d556d3f446a70ca.
Report an issue: GitHub.