risingwavelabs/risingwave · error
since_timestamp requires at least one upstream table
Error message
since_timestamp requires at least one upstream table
What it means
resolve_log_store_epoch resolves the unified change-log epoch for a streaming job's upstream tables. It rejects the call up-front when the caller supplies zero upstream table IDs, because computing a 'since' timestamp is meaningless without any table to read change logs from. This is a defensive validation against calling the API with an empty table set.
Source
Thrown at src/meta/src/barrier/context/context_impl.rs:196
}
fn mark_ready(&self, options: MarkReadyOptions) {
let is_global = matches!(&options, MarkReadyOptions::Global { .. });
self.scheduled_barriers.mark_ready(options);
if is_global {
self.set_status(BarrierManagerStatus::Running);
}
}
async fn resolve_log_store_epoch<'a>(
&'a self,
upstream_table_ids: impl Iterator<Item = TableId> + Send + 'a,
since_epoch: u64,
) -> MetaResult<SinceTimestampResolvedEpoch> {
let upstream_table_ids = upstream_table_ids.collect::<Vec<_>>();
if upstream_table_ids.is_empty() {
return Err(
anyhow::anyhow!("since_timestamp requires at least one upstream table").into(),
);
}
self.hummock_manager
.on_current_version_and_table_change_log(|version, table_change_log| {
let mut unified_log_epochs = None;
for &upstream_table_id in &upstream_table_ids {
let upstream_committed_epoch = version
.state_table_info
.info()
.get(&upstream_table_id)
.map(|info| info.committed_epoch)
.ok_or_else(|| {
anyhow::anyhow!(
"cannot get committed epoch for upstream table {}",
upstream_table_id
)
})?;View on GitHub (pinned to 6469eb736d)
Solutions
- Inspect the job whose upstream tables resolved to empty; verify it actually has upstream materialized views/sources in the catalog
- Fix the caller so it only invokes resolve_log_store_epoch when the upstream table list is non-empty (guard before collecting)
- If the job legitimately has no upstream table, change its design (e.g. use a source or datagen) — log-store resolution cannot work tableless
- If it's a recovery-time failure, restart recovery after fixing the catalog so upstream mappings are correct
Example fix
// before let epochs = manager.resolve_log_store_epoch(upstream_table_ids, since_epoch).await?; // after let tables: Vec<_> = upstream_table_ids.collect(); anyhow::ensure!(!tables.is_empty(), "job has no upstream tables; skip since_timestamp resolution"); let epochs = manager.resolve_log_store_epoch(tables.into_iter(), since_epoch).await?;
Defensive patterns
Strategy: validation
Validate before calling
let tables: Vec<TableId> = upstream_table_ids.collect();
if tables.is_empty() {
return Err(anyhow::anyhow!("no upstream tables to resolve since_timestamp"));
}
let resolved = manager.resolve_log_store_epoch(tables.into_iter(), since_epoch).await?; Try / catch
match manager.resolve_log_store_epoch(ids, epoch).await {
Ok(resolved) => use(resolved),
Err(e) if e.to_string().contains("requires at least one upstream table") => log::warn!("job has no upstream tables, skipping"),
Err(e) => return Err(e),
} Prevention
- Guard callers against empty upstream table sets before invoking
- Add unit tests for jobs with zero upstream dependencies
- Log upstream table collection results to catch resolution bugs early
When it happens
Trigger: Calling GlobalBarrierManager::resolve_log_store_epoch (via the barrier manager context) with an upstream_table_ids iterator that yields no elements — e.g. a streaming job with no upstream materialized-source/table dependencies, or an upstream ID collection bug upstream of the call.
Common situations: Creating or recovering a sink/job whose upstream resolution returned an empty set; a planner or catalog bug mapping a job to its upstream tables; races where upstream tables were dropped before this call.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- The cluster is recovering
- The cluster is recovering-adhoc
- since_timestamp epoch has not been resolved for snapshot bac
- The cluster is bootstrapping
- worker_id {} for actor {} does not exist
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/d0d19560ea479617.
Report an issue: GitHub.