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
- Wait for the in-flight operation on that database to finish, then retry the publish/init
- Check server logs to identify what held the lock (the timeout exists specifically to expose holders/deadlocks)
- If it persists and no operation is legitimately running, restart the spacetimedb process to clear stuck locks
- 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
- Serialize publishes to the same database (CI mutex / deploy queue)
- Avoid publishing while heavy reducer traffic runs on the target database
- Alert on repeated lock timeouts - they indicate a stuck holder or deadlock
- Keep the server on a current version; the lock timeout exists to expose holder issues
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
- unable to lock database {} for update
- unable to lock database {} for migration planning
- Write skew, you need to implement retries my man, T-dawg.
- Missing type name for ${typeBuilder.constructor.name ?? 'Typ
- Server already configured for host: {host}
AI-assisted analysis of clockworklabs/SpacetimeDB@fdd647dfac (2026-08-20).
Data as JSON: /api/errors/0223244c304dd2fa.
Report an issue: GitHub.