risingwavelabs/risingwave · error

no upstream while snapshot epoch not set

Error message

no upstream while snapshot epoch not set

What it means

In the snapshot backfill executor's execute_inner, the snapshot epoch must be initialized from the first upstream barrier. If snapshot_epoch is None but there is no upstream entry to read the epoch from, the executor cannot proceed and throws this error instead of panicking.

Source

Thrown at src/stream/src/executor/backfill/snapshot_backfill/executor.rs:199

                } else {
                    None
                }
            } else {
                // must go through snapshot backfill when having no upstream
                Some(snapshot_epoch)
            }
        } else {
            // when snapshot epoch is not set, the StreamNode must be created previously and has finished the backfill
            if cfg!(debug_assertions) {
                panic!(
                    "snapshot epoch not set. first_upstream_epoch: {:?}, first_recv_epoch: {:?}",
                    upstream.map(|(first_upstream_barrier, _)| first_upstream_barrier.epoch),
                    first_recv_barrier.epoch
                );
            } else {
                let (first_upstream_barrier, _) = upstream
                    .as_ref()
                    .ok_or_else(|| anyhow!("no upstream while snapshot epoch not set"))?;
                warn!(first_upstream_epoch = ?first_upstream_barrier.epoch, first_recv_epoch=?first_recv_barrier.epoch, "snapshot epoch not set");
                assert_eq!(first_upstream_barrier.epoch, first_recv_barrier.epoch);
                None
            }
        };
        let first_recv_barrier_epoch = first_recv_barrier.epoch;
        let initial_backfill_paused =
            first_recv_barrier.is_backfill_pause_on_startup(self.actor_ctx.fragment_id);
        yield Message::Barrier(first_recv_barrier);
        let mut backfill_state = BackfillState::new(
            self.progress_state_table,
            first_recv_barrier_epoch,
            self.upstream_table.pk_serializer().clone(),
        )
        .await?;

        let (mut barrier_epoch, mut need_report_finish, upstream) = {
            if let Some(snapshot_epoch) = should_snapshot_backfill {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Recover/retry the job so the meta service reconnects the upstream actor before this one starts
  2. Check meta logs for upstream fragment scheduling or actor creation failures
  3. Cancel and recreate the streaming job if the graph dependency is broken
  4. Upgrade to a version with fragment scheduling fixes if this occurs consistently at job creation
Defensive patterns

Strategy: retry

Try / catch

match execute_inner().await {
    Err(e) if e.to_string().contains("no upstream while snapshot epoch not set") => {
        // upstream actor missing: check meta scheduling logs and recover the job
    }
    r => r?,
}

Prevention

When it happens

Trigger: The executor's barrier alignment finishes without receiving any upstream message while the snapshot epoch was never set — i.e. the upstream channel list is empty at the point where the first barrier must establish the snapshot epoch.

Common situations: Upstream fragment not yet scheduled/connected when the backfill actor starts; upstream actor crashed before delivering its first barrier; mis-wired fragment dependency in the stream graph after a meta scheduling failure.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/fc721a79f43ce2a9. Report an issue: GitHub.