block/buzz · critical · anyhow::Error
Cannot derive a community host from BUZZ_RELAY_URL
Error message
Cannot derive a community host from BUZZ_RELAY_URL ({:?}); a resolvable host is required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true What it means
Fatal startup error: the relay derives its deployment community host from BUZZ_RELAY_URL via relay_url_authority(), and that returned an empty authority — the URL has no parseable host. With BUZZ_REQUIRE_RELAY_MEMBERSHIP=true, bootstrapping an empty-host community no request could ever resolve to is a misconfiguration, so startup fails fast.
Solutions
- Set BUZZ_RELAY_URL to a full URL with scheme and host: wss://relay.example.com (prod) or ws://localhost:3000 (dev)
- Ensure the host matches how clients will address the relay — the bootstrapped owner community is keyed to it
- Restart; if you truly did not want membership enforcement, BUZZ_REQUIRE_RELAY_MEMBERSHIP=false downgrades this to a warning
Example fix
# before export BUZZ_RELAY_URL=localhost:3000 # after export BUZZ_RELAY_URL=ws://localhost:3000
Defensive patterns
Strategy: validation
Validate before calling
# Deploy-time guard:
python3 - <<'EOF'
from urllib.parse import urlparse
import os
u = os.environ.get("BUZZ_RELAY_URL", "")
assert urlparse(u).scheme in ("ws", "wss") and urlparse(u).hostname, \
f"BUZZ_RELAY_URL must be a full ws:// or wss:// URL, got: {u!r}"
EOF Prevention
- Always configure BUZZ_RELAY_URL with an explicit ws:// or wss:// scheme
- The URL host defines the deployment community — keep it stable and matching how clients connect
When it happens
Trigger: BUZZ_RELAY_URL is empty, missing a scheme ("relay.example.com" instead of "wss://relay.example.com"), or otherwise unparseable, while BUZZ_REQUIRE_RELAY_MEMBERSHIP=true. Without enforcement the same condition only logs a warning and skips membership bootstrap.
Common situations: Setting just a host:port ("localhost:3000") without ws://; a templating bug injecting an empty variable into the URL; the var being consumed by a proxy config instead of the relay.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- BUZZ_RELAY_PRIVATE_KEY is required when…
- Redis pool creation failed
- RELAY_OWNER_PUBKEY required when…
- Configuration error
- Failed to backfill pubkey_allowlist (required when…
AI-assisted analysis of block/buzz@ef2aa1ae38 (2026-08-20).
Data as JSON: /api/errors/cc72b385f54a4938.
Report an issue: GitHub.
Appendix: source
Thrown at crates/buzz-relay/src/main.rs:354
));
}
// NIP-43 / multi-tenant: seed the deployment's *own* community before any
// membership backfill or owner bootstrap, so those writes are scoped to a
// real `(community_id, pubkey)` and not a global pubkey. The host is derived
// from `relay_url` with the *same* normalization request resolution uses
// (`relay_url_authority` → `normalize_host`), so the bootstrapped owner lands
// in exactly the community that live requests for this host will resolve to.
//
// `ensure_configured_community` is idempotent, so this is safe to run every
// startup. An empty authority (unparseable `relay_url`)
// is a misconfiguration — fail fast when membership is enforced rather than
// seeding an empty-host community that no request can ever resolve to.
let deployment_community = {
let host = buzz_relay::tenant::relay_url_authority(&config.relay_url);
if host.is_empty() {
if config.require_relay_membership {
return Err(anyhow::anyhow!(
"Cannot derive a community host from BUZZ_RELAY_URL ({:?}); a resolvable host is required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true",
config.relay_url
));
}
error!(
relay_url = %config.relay_url,
"Could not derive a community host from relay_url; skipping membership backfill/bootstrap (non-fatal, membership not required)"
);
None
} else {
match db.ensure_configured_community_for_bootstrap(&host).await {
Ok(record) => {
info!(host = %record.host, community = %record.id, "Deployment community ensured");
Some(record.id)
}
Err(e) => {
if config.require_relay_membership {
error!("Fatal: failed to ensure deployment community with membership enforcement enabled: {e}");View on GitHub (pinned to ef2aa1ae38)