{"record":{"id":"8f7bd4781467cee0","repo":"block/buzz","slug":"failed-to-backfill-pubkey-allowlist-required-when","errorCode":null,"errorMessage":"Failed to backfill pubkey_allowlist (required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true): {e}","messagePattern":"Failed to backfill pubkey_allowlist \\(required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true\\): (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/buzz-relay/src/main.rs","lineNumber":312,"sourceCode":"                }\n            }\n        }\n    };\n\n    // NIP-43: migrate any existing pubkey_allowlist entries to relay_members.\n    // Idempotent — safe to run every startup. Must run before bootstrap_owner\n    // so that existing allowlist users become relay members before the owner\n    // is promoted (otherwise enabling membership locks everyone out).\n    if let Some(community) = deployment_community {\n        match db.backfill_from_allowlist(community).await {\n            Ok(0) => {}\n            Ok(n) => info!(\"Backfilled {n} pubkey_allowlist entries into relay_members\"),\n            Err(e) => {\n                if config.require_relay_membership {\n                    error!(\n                        \"Fatal: failed to backfill allowlist with membership enforcement enabled: {e}\"\n                    );\n                    return Err(anyhow::anyhow!(\n                        \"Failed to backfill pubkey_allowlist (required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true): {e}\"\n                    ));\n                } else {\n                    error!(\"Failed to backfill pubkey_allowlist (non-fatal): {e}\");\n                }\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 {","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-relay/src/main.rs#L294-L330","documentation":"backfill_from_allowlist() migrates existing pubkey_allowlist entries into relay_members for the deployment community, deliberately before owner bootstrap so enabling membership does not lock existing users out. With enforcement on, any DB failure during this idempotent migration is fatal; without enforcement it is logged and skipped.","triggerScenarios":"DB write errors inserting relay_members rows; duplicate/conflicting rows from a partially completed earlier backfill; schema drift after skipped migrations.","commonSituations":"Enabling NIP-43 enforcement on an older deployment with a populated allowlist; a previous boot crashed mid-backfill; replica-promoted DB with constraint drift.","solutions":["Inspect {e} for the failing statement or constraint","Ensure migrations are current so relay_members matches the expected shape","Retry boot — the backfill is idempotent and resumes cleanly"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"# The backfill writes relay_members: confirm the table is reachable and writable.\npsql \"$DATABASE_URL\" -c 'select 1 from relay_members limit 1' || { echo 'relay_members unreadable'; exit 1; }","typeGuard":null,"tryCatchPattern":"# docker-compose: bounded restarts; the backfill is idempotent and resumes\nrelay:\n  restart: on-failure:5","preventionTips":["Apply migrations before enabling membership enforcement so relay_members exists","Run the enforcement rollout against a rehearsed copy of the allowlist first","Watch the 'Backfilled N pubkey_allowlist entries' log to confirm completion after restart"],"tags":["postgres","membership","nip-43","startup","backfill"],"backgroundTag":"database-write-failed","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}