clockworklabs/SpacetimeDB · error · WasmError

failed to look up materialized view args for view {}

Error message

failed to look up materialized view args for view {}

What it means

While refreshing a materialized view inside a procedure, the host looks up the view instance's arguments (its sender) via tx.view_instance_args(view_call). A None return means no stored instance/args row exists for this view call in the transaction's view of the state — the subscription or instance this refresh was triggered for is gone from the catalog.

Source

Thrown at crates/core/src/host/wasmtime/wasm_instance_env.rs:1785

        for view_call in views_for_refresh {
            let res: anyhow::Result<()> = (|| {
                let resolved = crate::host::module_host::resolve_view_for_refresh(
                    tx.as_ref().expect("procedure tx missing during view refresh"),
                    &module_def,
                    &view_call,
                )?;

                let table_id = resolved.table_id;
                let view_def = resolved.view_def;
                let view_name = &resolved.view_name;
                let fn_ptr = resolved.global_fn_ptr;
                let sender = tx
                    .as_ref()
                    .expect("procedure tx missing while looking up refreshed view args")
                    .view_instance_args(&view_call)
                    .ok_or_else(|| {
                        anyhow!(
                            "failed to look up materialized view args for view {}",
                            view_call.view_id
                        )
                    })?
                    .sender();

                let current_tx = tx.take().expect("procedure tx missing during view refresh");
                let (next_tx, call_result) = tx_slot.set(current_tx, || {
                    Self::call_view(caller, &view_call, view_name, fn_ptr, sender)
                });
                tx = Some(next_tx);
                let return_data = call_result?;

                let typespace = resolved.owning_def.typespace();
                let row_product_type = typespace
                    .resolve(view_def.product_type_ref)
                    .resolve_refs()?
                    .into_product()

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Retry the procedure — if the instance was legitimately removed the refresh may no longer apply, or the race has passed.
  2. Quiesce materialized-view subscriptions (stop writers) before teardown or maintenance procedures that refresh them.
  3. Republish to rebuild view-instance state if the catalog is suspected inconsistent.
  4. If it persists with stable subscriptions, report it with reproduction steps — it can indicate a host bookkeeping race.
Defensive patterns

Strategy: try-catch

Try / catch

// A missing view-instance row during refresh is usually a lifecycle race — retry once
match result {
    Err(e) if e.to_string().contains("materialized view args") => {
        retry_procedure_once().await
    }
    other => other,
}

Prevention

When it happens

Trigger: A materialized view instance (subscription) is dropped concurrently while a procedure triggers view refreshes, so its args row disappears mid-flight; or the view-instance catalog is missing rows the module expects after an inconsistent publish or a bookkeeping race.

Common situations: Clients unsubscribing from materialized views while writers and procedures run against those views; races between subscription lifecycle and procedure execution under heavy traffic; state left inconsistent after a failed update.

Related errors


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