clockworklabs/SpacetimeDB · error · anyhow::Error

unable to lock database {} for initialization

Error message

unable to lock database {} for initialization

What it means

try_init_host takes a per-replica write lock before creating or fetching the module host for a database. Lock acquisition is wrapped in a 5-second timeout (added to surface deadlocks during debugging); when the lock cannot be taken in time because another long-running operation is holding it, initialization fails with this error naming the database identity.

Source

Thrown at crates/core/src/host/host_controller.rs:458

        &self,
        database: Database,
        replica_id: u64,
    ) -> anyhow::Result<(watch::Receiver<ModuleHost>, Option<BootstrapCompletion>)> {
        // Try a read lock first.
        {
            if let Ok(guard) = self.acquire_read_lock(replica_id).await
                && let Some(host) = &*guard
            {
                trace!("cached host {}/{}", database.database_identity, replica_id);
                return Ok((host.module.subscribe(), None));
            }
        }

        // We didn't find a running module, so take a write lock.
        // Since [`tokio::sync::RwLock`] doesn't support upgrading of read locks,
        // we'll need to check again if a module was added meanwhile.
        let Ok(mut guard) = self.acquire_write_lock(replica_id).await else {
            bail!(
                "unable to lock database {} for initialization",
                database.database_identity
            );
        };
        if let Some(host) = &*guard {
            trace!(
                "cached host {}/{} (lock upgrade)",
                database.database_identity,
                replica_id
            );
            return Ok((host.module.subscribe(), None));
        }

        trace!("launch host {}/{}", database.database_identity, replica_id);

        // `HostController::clone` is fast,
        // as all of its fields are either `Copy` or wrapped in `Arc`.
        let this = self.clone();

View on GitHub (pinned to fdd647dfac)

Solutions

  1. Wait for the in-flight operation on that database to finish, then retry the publish/init
  2. Check server logs to identify what held the lock (the timeout exists specifically to expose holders/deadlocks)
  3. If it persists and no operation is legitimately running, restart the spacetimedb process to clear stuck locks
  4. Serialize publishes to the same database in your tooling (deploy queue, CI mutex)
Defensive patterns

Strategy: retry

Try / catch

# shell: retry while a concurrent op holds the replica lock (5s timeout)
for i in 1 2 3; do
  spacetime publish my-db --project-path . && exit 0
  echo "attempt $i: database lock busy - retrying" >&2
  sleep 10
done
exit 1

Prevention

When it happens

Trigger: A concurrent publish, update, or subscription workload holding the replica's host lock longer than 5 seconds (e.g. a reducer call or module task in flight, or a slow host initialization) while another request tries to initialize the same database; or a genuinely stuck/deadlocked holder that never releases.

Common situations: Two clients publishing or publishing+subscribing to the same database simultaneously; a previous operation hung; automated tooling retrying publishes in a tight loop against a busy replica.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@fdd647dfac (2026-08-20). Data as JSON: /api/errors/0223244c304dd2fa. Report an issue: GitHub.