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
- Read the embedded {err} — it is the error the view produced; fix the view logic or its SQL accordingly.
- Parameterize and validate any SQL the view returns; never splice unescaped values into it.
- Add unit tests for the view over edge-case inputs (empty tables, unusual args).
- 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
- Parameterize all SQL produced by raw-SQL views.
- Unit-test views with empty tables and unusual arguments.
- Handle error propagation in view code explicitly.
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
- view {:?} does not have a backing table
- view `{}` for view id `{}` not found in current module
- found is_anonymous={} in st_view, but {} in module when upda
- data key not found in return object
- data key not found in return object
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/336d291681836de4.
Report an issue: GitHub.