{"record":{"id":"e4100795a3bf37d8","repo":"block/buzz","slug":"failed-to-bootstrap-relay-owner-required-when-buz","errorCode":null,"errorMessage":"Failed to bootstrap relay owner (required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true): {e}","messagePattern":"Failed to bootstrap relay owner \\(required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true\\): (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/buzz-relay/src/main.rs","lineNumber":420,"sourceCode":"                }\n            }\n        }\n    }\n\n    // NIP-43: ensure the configured relay owner always holds the owner role\n    // within the deployment community.\n    if let (Some(community), Some(owner_pubkey)) =\n        (deployment_community, config.relay_owner_pubkey.as_ref())\n    {\n        match db.bootstrap_owner(community, owner_pubkey).await {\n            Ok(()) => info!(pubkey = %owner_pubkey, \"Relay owner bootstrapped\"),\n            Err(e) => {\n                if config.require_relay_membership {\n                    // Membership enforcement is on — a missing owner means no one\n                    // can administer the relay. Fail fast rather than silently start\n                    // in a broken state.\n                    error!(\"Fatal: failed to bootstrap relay owner with membership enforcement enabled: {e}\");\n                    return Err(anyhow::anyhow!(\n                        \"Failed to bootstrap relay owner (required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true): {e}\"\n                    ));\n                } else {\n                    error!(\n                        \"Failed to bootstrap relay owner (non-fatal, membership not required): {e}\"\n                    );\n                }\n            }\n        }\n    }\n\n    // NIP-33: backfill d_tag for any existing parameterized replaceable events\n    // that predate the column addition. Idempotent — no-ops when fully populated.\n    match db.backfill_d_tags().await {\n        Ok(0) => {}\n        Ok(n) => info!(\"Backfilled d_tag for {n} NIP-33 events\"),\n        Err(e) => error!(\"Failed to backfill d_tags: {e}\"),\n    }","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/block/buzz/blob/ef2aa1ae38fadcc0bc22b8bf6ed96b35933146be/crates/buzz-relay/src/main.rs#L402-L438","documentation":"Fatal startup error: db.bootstrap_owner(community, owner_pubkey) — the idempotent call guaranteeing RELAY_OWNER_PUBKEY holds the owner role in the deployment community — failed while BUZZ_REQUIRE_RELAY_MEMBERSHIP=true. A membership-enforcing relay without a bootstrapped owner cannot be administered, so the relay fails fast rather than start broken.","triggerScenarios":"DB failure during the owner upsert/role promotion: transient connection error, permission denied on the members/roles tables, or a schema/constraint mismatch from unapplied migrations.","commonSituations":"Same class as the other boot-time membership writes: Postgres not fully healthy at relay boot, least-privilege role missing rights, or a database restored without the full schema.","solutions":["Read the {e} detail to classify connectivity vs permissions vs schema","Verify the DB role can write the membership/role tables used by bootstrap_owner","Restart after Postgres is stable — the call is idempotent and re-runs safely every startup","Confirm RELAY_OWNER_PUBKEY is the intended admin key before retrying, since it will be promoted to owner"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"# Verify the role can write membership tables before deploy:\npsql \"$DATABASE_URL\" -c \"insert into relay_members (community_id, pubkey, role) values ('00000000-0000-0000-0000-000000000000','00','member') on conflict do nothing\" 2>&1 | head -1","typeGuard":null,"tryCatchPattern":"// Distinguish transient (restart with backoff) from permanent (grants/schema)\n// by the wrapped sqlx error text before alerting.","preventionTips":["bootstrap_owner runs every startup and is idempotent — restart is the fix once the DB cause is resolved","Ensure RELAY_OWNER_PUBKEY is correct before first boot; it will be promoted to owner"],"tags":["postgres","owner-bootstrap","nip-43","startup","buzz-relay"],"backgroundTag":"database-write-failed","analyzedSha":"ef2aa1ae38fadcc0bc22b8bf6ed96b35933146be","analyzedAt":"2026-08-20T04:38:24.874Z","contentChangedAt":"2026-08-20T04:38:24.874Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}