clockworklabs/SpacetimeDB · error

view {:?} does not have a backing table

Error message

view {:?} does not have a backing table

What it means

While resolving a view for refresh, the system reads the view's catalog row (st_views) and requires table_id — the backing table the view materializes into. A NULL table_id means the catalog view has no backing table, so refresh cannot proceed and resolution fails.

Source

Thrown at crates/core/src/host/module_host.rs:1177

    /// type-index references in the `ViewDef`.
    pub owning_def: &'a ModuleDef,
}

/// Lookup a module's [`ViewDef`] and check for consistency among
/// its readset, `st_view`, and the [`ModuleDef`].
pub(crate) fn resolve_view_for_refresh<'a>(
    tx: &MutTxId,
    module_def: &'a ModuleDef,
    view_call: &ViewCallInfo,
) -> anyhow::Result<ResolvedViewForRefresh<'a>> {
    let st_view = tx
        .lookup_st_view(view_call.view_id)
        .with_context(|| format!("failed to look up view {}", view_call.view_id))?;

    let view_id = st_view.view_id;
    let table_id = st_view
        .table_id
        .ok_or_else(|| anyhow::anyhow!("view {:?} does not have a backing table", view_id))?;

    let (global_fn_ptr, view_def, owning_def) = module_def
        .view_by_name_with_global_fn_ptr(&st_view.view_name.clone().into())
        .ok_or_else(|| {
            anyhow::anyhow!(
                "view `{}` for view id `{}` not found in current module",
                st_view.view_name,
                view_id
            )
        })?;

    let is_anonymous = view_def.is_anonymous;

    if st_view.is_anonymous != is_anonymous {
        return Err(anyhow::anyhow!(
            "found is_anonymous={} in st_view, but {} in module when updating view `{}`",
            st_view.is_anonymous,
            is_anonymous,

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Re-publish the module so the view catalog is rewritten: `spacetime publish <db>`.
  2. If reproducible and the data is disposable, delete and recreate the database (export first if needed).
  3. Capture server logs and report to SpacetimeDB with the module code that declares the view.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await refreshViews(db);
} catch (e) {
  if (String(e).includes('does not have a backing table')) {
    await spacetimePublish(dbName, modulePath); // rewrite view catalog, then retry
    return refreshViews(db);
  }
  throw e;
}

Prevention

When it happens

Trigger: Refreshing a view whose catalog row was written without a backing table (in-progress or interrupted schema change); refreshing an internal or system view that never has a backing table; catalog/module state drift around view features.

Common situations: Interrupted or partially failed module publishes that altered views; bugs in view catalog maintenance; early adoption of view features before stabilization.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/2448e91f856f3333. Report an issue: GitHub.