clockworklabs/SpacetimeDB · error · DBError
database {} already initialized
Error message
database {} already initialized What it means
RelationalDB::set_initialized records program metadata (identity, owner, program hash/bytes) in st_module. It errors when metadata already exists with a different program hash, database identity, or owner identity; the source marks this 'Probably a bug' because hosts should use the update/migrate path for already-initialized databases, not re-initialize.
Source
Thrown at crates/engine/src/relational_db.rs:444
/// See [`Self::open`] for further information.
pub fn set_initialized(&self, tx: &mut MutTx, program: Program) -> Result<(), DBError> {
log::trace!(
"[{}] DATABASE: set initialized owner={} program_hash={}",
self.database_identity,
self.owner_identity,
program.hash
);
// Probably a bug: the database is already initialized.
// Ignore if it would be a no-op.
if let Some(meta) = self.inner.metadata_mut_tx(tx)? {
if program.hash == meta.program_hash
&& self.database_identity == meta.database_identity
&& self.owner_identity == meta.owner_identity
{
return Ok(());
}
return Err(anyhow!("database {} already initialized", self.database_identity).into());
}
let row = StModuleRow {
database_identity: self.database_identity.into(),
owner_identity: self.owner_identity.into(),
program_kind: program.kind,
program_hash: program.hash,
program_bytes: program.bytes,
module_version: ONLY_MODULE_VERSION.into(),
};
Ok(tx.insert_via_serialize_bsatn(ST_MODULE_ID, &row).map(drop)?)
}
/// Obtain the [`Metadata`] of this database.
///
/// `None` if the database is not yet fully initialized.
pub fn metadata(&self) -> Result<Option<Metadata>, DBError> {
Ok(self.with_read_only(Workload::Internal, |tx| self.inner.metadata(tx))?)View on GitHub (pinned to 3653d2ed49)
Solutions
- Only call set_initialized when db.metadata()? returns None
- For an already-initialized database, route through the migration/update path instead of initialization
- If the existing database is disposable, drop and recreate it before initializing with the new program
Example fix
// before
let tx = db.begin_mut_tx(IsolationLevel::Serializable, Workload::Internal);
db.set_initialized(&mut tx, program)?;
// after: guard on existing metadata
if db.metadata()?.is_some() {
anyhow::bail!("database already initialized; use the update path");
}
let mut tx = db.begin_mut_tx(IsolationLevel::Serializable, Workload::Internal);
db.set_initialized(&mut tx, program)?; Defensive patterns
Strategy: validation
Validate before calling
// Guard set_initialized on existing metadata
match db.metadata()? {
None => { /* safe to initialize */ }
Some(meta) => {
anyhow::ensure!(
meta.program_hash == program.hash,
"database already initialized with a different program; use the update path"
);
return Ok(());
}
}
let mut tx = db.begin_mut_tx(IsolationLevel::Serializable, Workload::Internal);
db.set_initialized(&mut tx, program)?; Type guard
fn is_uninitialized(db: &RelationalDB) -> bool {
db.metadata().ok().flatten().is_none()
} Prevention
- Route republishes through update/migrate, reserving set_initialized for first publish
- Assert metadata().is_none() in tests before initializing
- Treat 'already initialized' as a host control-flow bug, not a user error
When it happens
Trigger: Calling set_initialized on a database whose metadata row already exists and whose program_hash/kind or identities differ from the Program being installed; a host publish flow that picks the initialize branch instead of the update branch on re-publish.
Common situations: Host control-flow bug choosing init instead of migrate during republish; test harnesses calling init twice with different schemas; publishing a different module binary where an update was intended.
Related errors
- ChangeTableAccessorName: `{table_name}` not found in new mod
- ChangeColumnAccessorName: `{table_name}` not found in new mo
- Column `{col_name}` not found in table `{table_name}`
- ChangeIndexSourceName: `{index_name}` not found in old modul
- ChangeIndexSourceName: `{index_name}` not found in new modul
AI-assisted analysis of clockworklabs/SpacetimeDB@3653d2ed49 (2026-08-20).
Data as JSON: /api/errors/86fc74cb91dc7c5c.
Report an issue: GitHub.