clockworklabs/SpacetimeDB · error

view call failed: {err}

Error message

view call failed: {err}

What it means

After invoking a view through the wasm result sink, the host decodes the sink's return code and collected bytes. A user error code — the view itself reported a failure through the documented channel — is surfaced as `view call failed: {err}` carrying the view's own error message. This is the view's runtime error, not a host malfunction; unexpected codes get a different message.

Source

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

                sender,
                args_source.0,
                result_sink,
                true,
            )?;

            Ok(code)
        })();

        caller.data_mut().instance_env.swap_func_type(prev_func_type);

        let result_bytes = {
            let env = caller.data_mut();
            env.take_bytes_sink(nested_result_sink.expect("nested view result sink missing"))
        };
        let code = call_result?;

        decode_view_result_sink_code(code, result_bytes).map_err(|err| match err {
            ViewResultSinkError::User(err) => anyhow!("view call failed: {err}"),
            ViewResultSinkError::UnexpectedCode(code) => anyhow!(
                "unexpected return code {code} from view call, expected 0, 2, or {failure}",
                failure = HOST_CALL_FAILURE.get()
            ),
        })
    }

    /// Aborts a mutable transaction,
    /// blocking until the transaction has been aborted.
    ///
    /// Returns `0` on success, or an error code otherwise.
    ///
    /// # Traps
    ///
    /// This function does not trap.
    ///
    /// # Errors
    ///

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Read the embedded {err} — it is the error the view produced; fix the view logic or its SQL accordingly.
  2. Parameterize and validate any SQL the view returns; never splice unescaped values into it.
  3. Add unit tests for the view over edge-case inputs (empty tables, unusual args).
  4. Republish the fixed module; materialized state corrects on the next evaluation.

Example fix

// before: raw-SQL view builds a query from unvalidated input
let sql = format("SELECT * FROM jobs WHERE owner = '{}'", sender.to_hex());

// after: parameterized query, value bound at execution
let sql = "SELECT * FROM jobs WHERE owner = $1".to_string();
// bind the sender identity as a parameter when executing
Defensive patterns

Strategy: try-catch

Validate before calling

// for raw-SQL views: validate the query shape before returning it from the view
let sql = build_query(args);
sqlparser::parse(&sql)?; // reject malformed SQL before the host executes it

Try / catch

let err = call_view(...).unwrap_err();
if let Some(msg) = err.to_string().strip_prefix("view call failed: ") {
    // this is the view's own error message — fix the view logic or its SQL
    report_view_error(msg);
}

Prevention

When it happens

Trigger: A view body returns an error during subscription evaluation or the in-procedure refresh path: raw-SQL views returning invalid SQL, view logic rejecting inputs (bad sender or args), or SDK-level error propagation inside the view.

Common situations: Raw-SQL views building queries from unvalidated data; views assuming row/column shapes that changed after a migration; views that error on edge-case inputs such as empty arguments or unknown senders.

Related errors


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