clockworklabs/SpacetimeDB · error
view evaluation failed during environment publication
Error message
view evaluation failed during environment publication
What it means
After applying an environment update and its transactional changes, the actor runs evaluate_subscribed_views on the updated instance. If a view traps or its outcome is not Success, the transaction is rolled back and the caller receives UpdateDatabaseResult::ErrorExecutingMigration with this message — the environment change itself was fine, but the module's subscribed views could not be evaluated against it, so publication is treated as a failed migration.
Solutions
- Inspect server logs to find which view trapped and fix its logic in the module.
- Ensure views only reference environment keys that still exist after the update.
- Fix the module, then republish; the failed transaction was rolled back so state is unchanged.
Example fix
// before: view reads a removed env key
let key = ctx.env_get("OLD_KEY").unwrap();
// after: tolerate missing keys
let key = ctx.env_get("OLD_KEY").unwrap_or_default(); Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: ensure every view-referenced env key exists in the new environment
for key in view_env_keys { assert!(new_environment.contains_key(key), "missing env key {key}"); } Try / catch
match result { UpdateDatabaseResult::ErrorExecutingMigration(e) if e.to_string().contains("view evaluation failed") => inspect_and_fix_views(), _ => {} } Prevention
- Write defensive views (no unwrap, default missing env keys)
- Test view evaluation with the new environment before publishing
- Keep views tolerant to env key changes
When it happens
Trigger: Publishing a database/environment update where at least one subscribed view traps during re-evaluation (panic, error, or non-Success ViewOutcome) after the environment rows were replaced.
Common situations: A view reads an environment key that was removed or renamed in the new environment; a buggy view reducer that panics on the new data; views incompatible with the newly published module.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Environment publish failed with HTTP
- Invalid publish response
- Permission denied publishing environment values
- view not found in database
- Aborted.
AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20).
Data as JSON: /api/errors/90279bb162504de3.
Report an issue: GitHub.
Appendix: source
Thrown at crates/core/src/host/wasm_common/module_host_actor.rs:849
let tx = db.begin_mut_tx(IsolationLevel::Serializable, Workload::Internal);
let (tx, _) = db.with_auto_rollback(tx, |tx| -> anyhow::Result<()> {
use spacetimedb_datastore::system_tables::{read_hash_from_col, StModuleFields, ST_MODULE_ID};
let row = tx
.iter(ST_MODULE_ID)?
.next()
.context("database program is not initialized")?;
anyhow::ensure!(
read_hash_from_col(row, StModuleFields::ProgramHash)? == self.info.module_hash,
"database program changed before publication"
);
crate::db::environment::replace(db, tx, self.info.module_def.environment(), &environment)?;
Ok(())
})?;
let (out, _, trapped) = self.evaluate_subscribed_views(tx, inst)?;
if trapped || out.outcome != ViewOutcome::Success {
let (_, metrics, reducer) = db.rollback_mut_tx(out.tx);
db.report_mut_tx_metrics(reducer, metrics, None);
return Ok(UpdateDatabaseResult::ErrorExecutingMigration(anyhow::anyhow!(
"view evaluation failed during environment publication"
)));
}
let event = ModuleEvent {
timestamp: Timestamp::now(),
caller_identity: self.info.owner_identity,
caller_connection_id: None,
function_call: ModuleFunctionCall::update(),
status: EventStatus::Committed(DatabaseUpdate::default()),
reducer_return_value: None,
execution_budget_used: out.execution_budget_used,
host_execution_duration: out.total_duration,
request_id: None,
timer: None,
};
let durable_offset = db.durable_tx_offset();
let CommitAndBroadcastEventSuccess { tx_offset, .. } =
commit_and_broadcast_event(&self.info.subscriptions, None, event, out.tx);View on GitHub (pinned to eddf9f5014)