risingwavelabs/risingwave · error

table id {table_id} may have been dropped

Error message

table id {table_id} may have been dropped

What it means

In snapshot batch query setup (`batch_query_epoch`, src/frontend/src/scheduler/snapshot.rs:181), each table id in the query is looked up in the snapshot's `state_table_info` to obtain its committed epoch. If a table id is missing from the mapping, the code assumes the table `may have been dropped` between query planning and snapshot epoch resolution, and returns this anyhow error (surfaced as `SchedulerError::Internal`).

Source

Thrown at src/frontend/src/scheduler/snapshot.rs:181

/// A reference to a frontend-pinned snapshot.
pub type PinnedSnapshotRef = Arc<PinnedSnapshot>;

impl PinnedSnapshot {
    fn batch_query_epoch(
        &self,
        read_storage_tables: &HashSet<TableId>,
    ) -> Result<Epoch, SchedulerError> {
        // use the min committed epoch of tables involved in the scan
        let epoch = read_storage_tables
            .iter()
            .map(|table_id| {
                self.value
                    .state_table_info
                    .info()
                    .get(table_id)
                    .map(|info| Epoch(info.committed_epoch))
                    .ok_or_else(|| anyhow!("table id {table_id} may have been dropped"))
            })
            .try_fold(None, |prev_min_committed_epoch, committed_epoch| {
                committed_epoch.map(|committed_epoch| {
                    if let Some(prev_min_committed_epoch) = prev_min_committed_epoch
                        && prev_min_committed_epoch <= committed_epoch
                    {
                        Some(prev_min_committed_epoch)
                    } else {
                        Some(committed_epoch)
                    }
                })
            })?
            .unwrap_or_else(Epoch::now);
        Ok(epoch)
    }

    pub fn version(&self) -> &FrontendHummockVersion {
        &self.value

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Re-run the query; if the object was intentionally dropped it should now fail with a clear not-found error instead.
  2. Verify the table/MV still exists (`SHOW MATERIALIZED VIEWS;` / `SHOW TABLES;`) and recreate it if it was dropped.
  3. Avoid dropping a table while queries against it are in flight; coordinate DDL and query workloads.
  4. If the table exists but the error persists, check meta consistency and re-create the object or restart the meta service.

Example fix

// before: SELECT * FROM mv;  -- dropped concurrently
// after
CREATE MATERIALIZED VIEW IF NOT EXISTS mv AS SELECT ...;
SELECT * FROM mv;
Defensive patterns

Strategy: retry

Validate before calling

-- Check the object still exists before querying
SELECT 1 FROM rw_catalog.rw_tables WHERE table_id = <id>;
SELECT 1 FROM rw_catalog.rw_materialized_views WHERE name = 'mv';

Try / catch

match scheduler_result {
    Err(e) if e.to_string().contains("may have been dropped") => {
        // transient DDL race: re-plan and retry once
        retry_query_once();
    }
    r => r?,
}

Prevention

When it happens

Trigger: Running a batch query whose plan references a state table that is absent from the meta snapshot: the table (or its owning MV/index) was dropped concurrently after the query was planned.

Common situations: Race between `DROP TABLE`/`DROP MATERIALIZED VIEW` and a running SELECT against that object; stale cached plans referencing removed tables.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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