{"record":{"id":"d814fe4fcf837f7a","repo":"clockworklabs/SpacetimeDB","slug":"database-ownership-changed-before-reset","errorCode":null,"errorMessage":"database ownership changed before reset","messagePattern":"database ownership changed before reset","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/standalone/src/lib.rs","lineNumber":451,"sourceCode":"        anyhow::ensure!(\n            database.owner_identity == *caller_identity,\n            \"database ownership changed before deletion\"\n        );\n        self.control_db.delete_database(database.id)?;\n\n        for instance in self.control_db.get_replicas_by_database(database.id)? {\n            self.delete_replica(instance.id).await?;\n        }\n\n        Ok(())\n    }\n\n    async fn reset_database(&self, caller_identity: &Identity, spec: DatabaseResetDef) -> anyhow::Result<()> {\n        let previous = self\n            .control_db\n            .get_database_by_identity(&spec.database_identity)?\n            .with_context(|| format!(\"Database `{}` does not exist\", spec.database_identity))?;\n        anyhow::ensure!(\n            previous.owner_identity == *caller_identity,\n            \"database ownership changed before reset\"\n        );\n        let previous = self.control_db.with_initialization_generation(previous)?;\n        let environment = spacetimedb_lib::environment::EnvironmentUpdate {\n            values: spec.environment,\n            remove: spec.environment_remove,\n            replace: spec.environment_replace,\n        }\n        .resulting_values(&Default::default())?;\n        let mut database = previous.clone();\n        let program = match spec.program_bytes {\n            Some(bytes) => {\n                let host_type = spec.host_type.unwrap_or(database.host_type);\n                Program::from_bytes(host_type.into(), &bytes[..])\n            }\n            None => {\n                // A reset without an artifact retains the currently committed","sourceCodeStart":433,"sourceCodeEnd":469,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/eddf9f5014579a50d4b67630e28b6e15cad9c4af/crates/standalone/src/lib.rs#L433-L469","documentation":"`reset_database` re-reads the database from the control DB and asserts the stored `owner_identity` still equals the caller before applying the reset (new program/environment). Because a reset replaces the database's initial program, replicas, and environment, only the current owner may perform it. This guard fires when ownership changed after the earlier lookup or the caller is not the owner.","triggerScenarios":"Calling `reset_database(caller_identity, DatabaseResetDef)` where `previous.owner_identity != caller_identity` — the database was re-published by or transferred to a different identity, or the caller passes a different identity than the one used to publish.","commonSituations":"Rotated service accounts or CI identities: publish was done with identity A but reset automation runs with identity B; shared team databases where one member re-created the database under their own identity.","solutions":["Reset using the identity that currently owns the database (verify owner via database metadata).","Re-authenticate as the original publishing identity if it still owns the database.","Re-create the database under the caller's identity if ownership cannot be recovered, then apply the reset definition to the new database.","Coordinate with the current owner to perform the reset, or have ownership formally reassigned before resetting."],"exampleFix":"// before\nawait standalone.reset_database(identityA, reset_def) // database now owned by identityB\n// after\nawait standalone.reset_database(current_owner_identity /* identityB */, reset_def)","handlingStrategy":"validation","validationCode":"let previous = control_db.get_database_by_identity(&spec.database_identity)?\n    .context(\"database does not exist\")?;\nif previous.owner_identity != caller_identity {\n    // resolve current owner before resetting\n    return Err(anyhow!(\"reset requires owner identity\"));\n}","typeGuard":"fn can_reset(db: &Database, caller: &Identity) -> bool { db.owner_identity == *caller }","tryCatchPattern":null,"preventionTips":["Re-authenticate as the publishing identity in CI before reset operations","Check owner identity from database metadata before every reset","Avoid mixing team members' identities for publish/reset of shared databases"],"tags":["rust","ownership","authorization","database"],"backgroundTag":"permission-denied","analyzedSha":"eddf9f5014579a50d4b67630e28b6e15cad9c4af","analyzedAt":"2026-09-20T12:15:59.611Z","contentChangedAt":"2026-09-20T12:15:59.611Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}