risingwavelabs/risingwave · error

since_timestamp is too new for upstream table {}: requested

Error message

since_timestamp is too new for upstream table {}: requested epoch {}, resolved snapshot epoch {}, latest changelog epoch {}

What it means

Although a changelog entry was found, its checkpoint epoch is >= the upstream committed epoch, meaning the resolution landed on the newest checkpoint (end-of-log). Such a snapshot epoch is not a usable historical snapshot for since-timestamp backfill, so it is rejected.

Source

Thrown at src/meta/src/barrier/context/context_impl.rs:132

        Ok(index) => index,
        Err(index) => index,
    };
    let snapshot_epoch = change_log
        .get(snapshot_epoch_index)
        .ok_or_else(|| {
            anyhow::anyhow!(
                "since_timestamp is later than the latest changelog of upstream table {}: requested epoch {}, latest changelog epoch {}",
                table_id,
                since_epoch,
                upstream_committed_epoch,
            )
        })?
        .checkpoint_epoch;
    // A request inside the latest changelog entry may be smaller than
    // `upstream_committed_epoch`, but still resolve to the latest checkpoint.
    // That end-of-log case is not a usable historical snapshot epoch.
    if snapshot_epoch >= upstream_committed_epoch {
        return Err(anyhow::anyhow!(
            "since_timestamp is too new for upstream table {}: requested epoch {}, resolved snapshot epoch {}, latest changelog epoch {}",
            table_id,
            since_epoch,
            snapshot_epoch,
            upstream_committed_epoch,
        )
        .into());
    }
    let epochs = change_log
        .range((snapshot_epoch_index + 1)..)
        .map(|epoch_log| {
            (
                epoch_log.non_checkpoint_epochs.clone(),
                epoch_log.checkpoint_epoch,
            )
        })
        .collect::<Vec<_>>();

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Supply an earlier since_timestamp that resolves to an older checkpoint
  2. Retry creating the backfill shortly after upstream commits new data
  3. Use a plain snapshot backfill without since_timestamp if the latest state is acceptable

Example fix

-- before
SINCE_TIMESTAMP = now();
-- after
SINCE_TIMESTAMP = now() - interval '5 minutes';
Defensive patterns

Strategy: validation

Validate before calling

if resolved_snapshot_epoch >= upstream_committed_epoch {
    return Err("since_timestamp resolves to the latest checkpoint; choose an earlier time");
}

Type guard

fn is_historical_snapshot(snap: u64, committed: u64) -> bool { snap < committed }

Try / catch

match create_snapshot_backfill(...).await {
    Err(e) if e.contains("too new for upstream table") => use_earlier_since_timestamp(),
    other => other,
}

Prevention

When it happens

Trigger: resolve_since_timestamp_log_store_epoch when binary search resolves to the latest entry whose checkpoint_epoch >= upstream_committed_epoch — the requested time falls within the newest changelog interval.

Common situations: since_timestamp set too close to 'now' so it maps onto the latest checkpoint; upstream table caught up fully before the backfill was created.

Related errors


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