{"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":335,"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":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-relay/src/main.rs#L317-L353","documentation":"bootstrap_owner() guarantees the configured RELAY_OWNER_PUBKEY holds the owner role within the deployment community. With enforcement on, a failed bootstrap means no one can administer the relay, so startup aborts with the DB error appended; without enforcement the failure is logged non-fatally.","triggerScenarios":"DB failure upserting the owner's membership role; community/relay_members rows in a state the bootstrap cannot satisfy (e.g. conflicting prior owner rows).","commonSituations":"Owner pubkey rotated without reconciling old rows; transient DB errors at boot; restored database with inconsistent membership state.","solutions":["Check the DB error detail, resolve, and retry boot — the operation is idempotent","Inspect the community and relay_members rows for the owner pubkey for conflicts","Confirm RELAY_OWNER_PUBKEY is the intended 64-char hex key and not a stale value"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"# Owner bootstrap needs a writable community + membership rows.\npsql \"$DATABASE_URL\" -tAc \"select count(*) from relay_members\" | grep -qv '^0$' || echo 'warn: no members yet — bootstrap will create the owner'","typeGuard":null,"tryCatchPattern":"# k8s: transient boot failures resolve on restart; bootstrap is idempotent\nspec:\n  restartPolicy: Always","preventionTips":["Verify RELAY_OWNER_PUBKEY matches the intended admin before deploy","When rotating the owner key, plan the handover rather than swapping env blindly","Confirm 'Relay owner bootstrapped' appears in startup logs after enabling enforcement"],"tags":["postgres","membership","nip-43","startup","owner","bootstrap"],"backgroundTag":"database-write-failed","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}