{"record":{"id":"86fc74cb91dc7c5c","repo":"clockworklabs/SpacetimeDB","slug":"database-already-initialized","errorCode":null,"errorMessage":"database {} already initialized","messagePattern":"database (.+?) already initialized","errorType":"exception","errorClass":"DBError","httpStatus":null,"severity":"error","filePath":"crates/engine/src/relational_db.rs","lineNumber":444,"sourceCode":"    /// See [`Self::open`] for further information.\n    pub fn set_initialized(&self, tx: &mut MutTx, program: Program) -> Result<(), DBError> {\n        log::trace!(\n            \"[{}] DATABASE: set initialized owner={} program_hash={}\",\n            self.database_identity,\n            self.owner_identity,\n            program.hash\n        );\n\n        // Probably a bug: the database is already initialized.\n        // Ignore if it would be a no-op.\n        if let Some(meta) = self.inner.metadata_mut_tx(tx)? {\n            if program.hash == meta.program_hash\n                && self.database_identity == meta.database_identity\n                && self.owner_identity == meta.owner_identity\n            {\n                return Ok(());\n            }\n            return Err(anyhow!(\"database {} already initialized\", self.database_identity).into());\n        }\n        let row = StModuleRow {\n            database_identity: self.database_identity.into(),\n            owner_identity: self.owner_identity.into(),\n\n            program_kind: program.kind,\n            program_hash: program.hash,\n            program_bytes: program.bytes,\n            module_version: ONLY_MODULE_VERSION.into(),\n        };\n        Ok(tx.insert_via_serialize_bsatn(ST_MODULE_ID, &row).map(drop)?)\n    }\n\n    /// Obtain the [`Metadata`] of this database.\n    ///\n    /// `None` if the database is not yet fully initialized.\n    pub fn metadata(&self) -> Result<Option<Metadata>, DBError> {\n        Ok(self.with_read_only(Workload::Internal, |tx| self.inner.metadata(tx))?)","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/3653d2ed498fddbd83b7062aa6bf8970e18635ec/crates/engine/src/relational_db.rs#L426-L462","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nlet tx = db.begin_mut_tx(IsolationLevel::Serializable, Workload::Internal);\ndb.set_initialized(&mut tx, program)?;\n\n// after: guard on existing metadata\nif db.metadata()?.is_some() {\n    anyhow::bail!(\"database already initialized; use the update path\");\n}\nlet mut tx = db.begin_mut_tx(IsolationLevel::Serializable, Workload::Internal);\ndb.set_initialized(&mut tx, program)?;","handlingStrategy":"validation","validationCode":"// Guard set_initialized on existing metadata\nmatch db.metadata()? {\n    None => { /* safe to initialize */ }\n    Some(meta) => {\n        anyhow::ensure!(\n            meta.program_hash == program.hash,\n            \"database already initialized with a different program; use the update path\"\n        );\n        return Ok(());\n    }\n}\nlet mut tx = db.begin_mut_tx(IsolationLevel::Serializable, Workload::Internal);\ndb.set_initialized(&mut tx, program)?;","typeGuard":"fn is_uninitialized(db: &RelationalDB) -> bool {\n    db.metadata().ok().flatten().is_none()\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","spacetimedb","initialization","lifecycle","publish"],"backgroundTag":"already-initialized","analyzedSha":"3653d2ed498fddbd83b7062aa6bf8970e18635ec","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}