risingwavelabs/risingwave · error
no table changelog found for upstream table {} when resolvin
Error message
no table changelog found for upstream table {} when resolving since_timestamp What it means
When resolving a since_timestamp into a concrete log-store epoch for a snapshot backfill, the upstream table's change log entry is missing entirely from TableChangeLogs. The resolver needs at least one changelog entry to map the since epoch to a snapshot checkpoint epoch.
Source
Thrown at src/meta/src/barrier/context/context_impl.rs:64
BarrierManagerStatus, BarrierWorkerRuntimeInfoSnapshot, BatchRefreshInfo, Command,
CreateStreamingJobCommandInfo, CreateStreamingJobType, DatabaseRuntimeInfoSnapshot,
RecoveryReason, ReplaceStreamJobPlan, Scheduled,
};
use crate::hummock::CommitEpochInfo;
use crate::manager::LocalNotification;
use crate::model::FragmentDownstreamRelation;
use crate::serving::{fetch_serving_infos, sync_serving_table_vnode_mappings_to_hummock};
use crate::stream::{SourceChange, cleanup_dropped_streaming_jobs};
use crate::{MetaError, MetaResult};
fn resolve_since_timestamp_log_store_epoch(
table_id: TableId,
since_epoch: u64,
upstream_committed_epoch: u64,
table_change_log: &TableChangeLogs,
) -> MetaResult<SinceTimestampResolvedEpoch> {
let change_log = table_change_log.get(&table_id).ok_or_else(|| {
anyhow::anyhow!(
"no table changelog found for upstream table {} when resolving since_timestamp",
table_id
)
})?;
let Some(first_log) = change_log.first() else {
return Err(anyhow::anyhow!(
"empty table changelog found for upstream table {} when resolving since_timestamp",
table_id
)
.into());
};
let first_checkpoint_epoch = first_log.checkpoint_epoch;
if since_epoch < first_checkpoint_epoch {
return Err(anyhow::anyhow!(
"since_timestamp is earlier than the retained changelog of upstream table {}: requested epoch {}, first retained checkpoint epoch {}",
table_id,
since_epoch,
first_checkpoint_epoch,View on GitHub (pinned to 6469eb736d)
Solutions
- Ensure the upstream table's changelog is registered before creating the snapshot backfill
- Retry after the next barrier collects change logs
- Verify the upstream table id is correct
- Report as a bug if the table clearly has changelogs
Defensive patterns
Strategy: validation
Validate before calling
if table_change_log.get(&table_id).is_none() {
return Err("upstream changelog not registered yet");
} Type guard
fn has_changelog(logs: &TableChangeLogs, id: &TableId) -> bool {
logs.contains_key(id)
} Try / catch
match create_snapshot_backfill(...).await {
Err(e) if e.contains("no table changelog found") => retry_after_next_barrier(),
other => other,
} Prevention
- Wait for upstream changelog registration before backfill creation
- Retry on the next barrier
- Verify upstream table id correctness
When it happens
Trigger: Calling resolve_since_timestamp_log_store_epoch (via resolve_log_store_epoch during barrier creation for a snapshot backfill) with a table_id absent from table_change_log.
Common situations: Upstream table changelog not yet registered in the barrier state; upstream MV/table created but no changelog collected yet; internal state inconsistency after recovery.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- since_timestamp is earlier than the retained changelog of up
- since_timestamp is later than the latest changelog of upstre
- empty table changelog found for upstream table {} when resol
- since_timestamp is not before the committed epoch of upstrea
- since_timestamp is too new for upstream table {}: requested
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/1cf940b19d3633e1.
Report an issue: GitHub.