{"record":{"id":"c4ceb4f98b2245af","repo":"clockworklabs/SpacetimeDB","slug":"database-ownership-changed-before-publication","errorCode":null,"errorMessage":"database ownership changed before publication","messagePattern":"database ownership changed before publication","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/standalone/src/lib.rs","lineNumber":336,"sourceCode":"\n                let program_hash = self.program_store.put(&spec.program_bytes).await?;\n\n                debug_assert_eq!(_hash_for_assert, program_hash);\n\n                let (database, replica) =\n                    self.control_db\n                        .upsert_database_with_environment(database, None, environment, &[])?;\n                // The leader nomination and input are durable already. If this\n                // waiter is cancelled, ordinary lookup resumes the same input.\n                self.on_insert_replica(&replica).await?;\n                debug_assert_eq!(database.id, replica.database_id);\n\n                Ok(None)\n            }\n            // The database already exists, so we'll try to update it.\n            // If that fails, we'll keep the old one.\n            Some(database) => {\n                anyhow::ensure!(\n                    database.owner_identity == *publisher,\n                    \"database ownership changed before publication\"\n                );\n                let database_id = database.id;\n                let database_identity = database.database_identity;\n\n                let leader = self.leader(database_id).await?;\n                let update_result = leader\n                    .update(\n                        database,\n                        spec.host_type,\n                        spec.program_bytes.to_vec().into(),\n                        policy,\n                        update,\n                        spec.expected_module_version,\n                    )\n                    .await?;\n                if update_result.was_successful() {","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/eddf9f5014579a50d4b67630e28b6e15cad9c4af/crates/standalone/src/lib.rs#L318-L354","documentation":"When updating an existing database, standalone verifies the publisher's identity equals the database's stored owner_identity before applying the new program. If the owner differs — meaning ownership was reassigned or the row changed since the caller last read it — the ensure! aborts the publication with this message so a non-owner cannot overwrite the module.","triggerScenarios":"Calling publish_database for an existing database with a publisher identity that differs from database.owner_identity, e.g. publishing under a different identity/key after the database was transferred or created by another account.","commonSituations":"A teammate tries to publish a database owned by another identity; switching local keys/credentials between publishes; automated jobs running with the wrong service identity.","solutions":["Publish using the identity that owns the database (the original publisher's key/credentials).","If ownership legitimately changed, verify the new owner_identity on the server and publish as that owner.","Transfer or recreate the database under the identity you intend to publish with."],"exampleFix":"// before: publishing with wrong identity\nawait client.publish(db, program, { identity: devIdentity }); // not owner\n\n// after: publish as owner\nawait client.publish(db, program, { identity: ownerIdentity });","handlingStrategy":"validation","validationCode":"// verify ownership before publishing\nconst db = await client.getDatabase(dbIdentity);\nif (db && db.owner_identity !== myIdentity) throw new Error('not the database owner');","typeGuard":"const isOwner = (db, identity) => db == null || db.owner_identity === identity;","tryCatchPattern":"try { publish(); } catch (e) { if (e.message.includes('ownership changed')) { switchToOwnerCredentials(); retry(); } else throw e; }","preventionTips":["Publish with the same identity that created the database","Track ownership transfers and update deploy credentials","Keep service identities consistent across CI jobs"],"tags":["publish","ownership","authorization","standalone"],"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"}