{"record":{"id":"8a653faddcc82ffe","repo":"block/buzz","slug":"relay-url-host-host-is-not-mapped-to-a-communi","errorCode":null,"errorMessage":"RELAY_URL host '{host}' is not mapped to a community.\nbuzz-admin operates on the configured relay's community; ensure the relay has started and seeded its community (or set RELAY_URL to a mapped host).","messagePattern":"RELAY_URL host '(.+?)' is not mapped to a community\\.\nbuzz-admin operates on the configured relay's community; ensure the relay has started and seeded its community \\(or set RELAY_URL to a mapped host\\)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/buzz-admin/src/main.rs","lineNumber":464,"sourceCode":"/// `buzz-admin` runs inside the relay container (`compose exec relay\n/// buzz-admin …`), so it shares the relay's `RELAY_URL` and resolves the same\n/// single community against the durable `communities` host map. This is\n/// deliberately NOT a default tenant: an unmapped host fails closed with an\n/// error, mirroring the relay's own `bind_community` row-zero seam. The CLI is\n/// single-community per invocation — there is no cross-community sweep.\nasync fn resolve_admin_tenant(db: &Db) -> Result<TenantContext> {\n    let relay_url =\n        std::env::var(\"RELAY_URL\").unwrap_or_else(|_| \"ws://localhost:3000\".to_string());\n    // Derive the authority the *same* way startup seeding and live request\n    // resolution do (`buzz_core::tenant::relay_url_authority`): host plus an\n    // explicit non-default port, IPv6 brackets preserved. A plain\n    // `Url::host_str()` drops the port/brackets, so for `ws://localhost:3000`\n    // the admin would look up `localhost` while startup seeded `localhost:3000`\n    // — and `wss://relay.example:8443` would resolve `relay.example`. Sharing\n    // the helper keeps buzz-admin byte-identical to the community startup seeds.\n    let host = relay_url_authority(&relay_url);\n    let record = db.lookup_community_by_host(&host).await?.ok_or_else(|| {\n        anyhow::anyhow!(\n            \"RELAY_URL host '{host}' is not mapped to a community.\\n\\\n             buzz-admin operates on the configured relay's community; ensure the \\\n             relay has started and seeded its community (or set RELAY_URL to a \\\n             mapped host).\"\n        )\n    })?;\n    Ok(TenantContext::resolved(record.id, record.host))\n}\n\nasync fn reconcile_channels(\n    channel_arg: Option<String>,\n    relay_key_arg: Option<String>,\n) -> Result<()> {\n    use buzz_core::kind::KIND_NIP29_GROUP_ADMINS;\n    use buzz_db::event::EventQuery;\n\n    let db = connect_db().await?;\n","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-admin/src/main.rs#L446-L482","documentation":"resolve_admin_tenant() derives the authority from RELAY_URL (default ws://localhost:3000) using buzz_core::tenant::relay_url_authority — host plus explicit non-default port, IPv6 brackets preserved — and then looks that host up in the communities table via lookup_community_by_host. The error means no community row matches that authority: the relay has never started (startup seeding creates the mapping), it seeded under a different host string, or RELAY_URL points somewhere else. The shared helper guarantees the admin CLI derives the key byte-identically to how the relay seeded it (e.g. localhost:3000, not localhost).","triggerScenarios":"Running buzz-admin against a fresh database where `just relay` has never run; setting RELAY_URL=ws://localhost:3000 while the relay was seeded behind a proxy as relay.example.com (or vice versa); changing the relay's port so the authority string (host:port) no longer matches the seeded row; running the admin CLI against the wrong DATABASE_URL so it queries an empty/unrelated communities table.","commonSituations":"Dev database reset (docker volume wiped) without restarting the relay; staging relay seeded via a public hostname but the operator exports the internal hostname; port mismatch — relay reachable on 3000 but seeded under 443/default so the stored host lacks the :3000 suffix; multi-community database where the admin points at a host nobody seeded.","solutions":["Start the relay once against the same DATABASE_URL (`just relay`) so startup seeding inserts the community row for its host, then re-run buzz-admin.","Set RELAY_URL to the exact public URL clients use for that relay (host AND port), so relay_url_authority produces the same string that was seeded — e.g. wss://relay.example.com, not the internal host:port if seeding happened at the edge.","Verify the mapping directly in Postgres: `SELECT id, host FROM communities;` and compare the host value character-by-character with the authority you expect from RELAY_URL.","Confirm DATABASE_URL points at the same database the relay writes to — a mismatched DB looks exactly like an unmapped host."],"exampleFix":"# before: relay never started on this DB\nRELAY_URL=ws://localhost:3000 buzz-admin ...\n# error: RELAY_URL host 'localhost:3000' is not mapped to a community.\n\n# after: seed first, then administer\njust relay &            # startup seeding maps localhost:3000 -> community\nRELAY_URL=ws://localhost:3000 buzz-admin ...","handlingStrategy":"validation","validationCode":"-- Verify the community mapping exists before running buzz-admin:\nSELECT host FROM communities WHERE host = 'localhost:3000'; -- must return the row your RELAY_URL derives to","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always start the relay once against a fresh database before running admin commands.","Use the exact public URL for RELAY_URL that clients use — authority derivation includes non-default ports.","Keep DATABASE_URL for admin jobs identical to the relay's; a different DB mimics an unmapped host."],"tags":["buzz-admin","multi-tenant","community-resolution","relay-url","seeding"],"backgroundTag":"tenant-resolution-failed","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}