{"record":{"id":"7bf2568e6fdb1fe9","repo":"block/buzz","slug":"cannot-derive-community-host-pass-host-or-set-r","errorCode":null,"errorMessage":"cannot derive community host; pass --host or set RELAY_URL","messagePattern":"cannot derive community host; pass --host or set RELAY_URL","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/buzz-deletion/src/lib.rs","lineNumber":521,"sourceCode":"            anyhow::bail!(\"database-only command reached full-service dispatcher\")\n        }\n    }\n}\n\nfn resolve_submit_host(host: Option<&str>, relay_url: Option<&str>) -> Result<String> {\n    if let Some(host) = host {\n        let host = host.trim();\n        if host.is_empty() {\n            anyhow::bail!(\"--host must not be empty\");\n        }\n        return Ok(host.to_owned());\n    }\n\n    let relay_url = relay_url\n        .map(str::trim)\n        .filter(|value| !value.is_empty())\n        .ok_or_else(|| {\n            anyhow::anyhow!(\"cannot derive community host; pass --host or set RELAY_URL\")\n        })?;\n    let host = buzz_core::tenant::relay_url_authority(relay_url);\n    if host.is_empty() {\n        anyhow::bail!(\n            \"cannot derive community host from RELAY_URL; pass --host or set a valid RELAY_URL\"\n        );\n    }\n    Ok(host)\n}\n\nasync fn connect_store() -> Result<DeletionStore> {\n    let database_url = required_env(\"DATABASE_URL\")?;\n    let db = Db::new(\n        &DbConfig {\n            database_url,\n            max_connections: env_parse(\"BUZZ_DB_POOL_SIZE\", 20),\n            ..DbConfig::default()\n        }","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/block/buzz/blob/dad5a33865fc81a2e55b3b60746632f615ec1e3a/crates/buzz-deletion/src/lib.rs#L503-L539","documentation":"buzz-deletion tooling is tenant-scoped: every purge operation needs to know which community (host) it acts on. The host comes from the --host flag when given (non-empty after trim), otherwise it is derived from RELAY_URL via buzz_core::tenant::relay_url_authority. When neither --host nor a non-empty RELAY_URL is available, resolution bails with this error before any database work starts.","triggerScenarios":"Invoking the deletion CLI/library entry point in an environment with no RELAY_URL (bare cron job, minimal container) and without passing --host; RELAY_URL set to an empty string or whitespace, which the trim+filter treats as absent.","commonSituations":"Scheduled cleanup jobs that inherit a stripped environment; scripts written against a dev box (where the shell had RELAY_URL exported) later run in CI; .env not sourced in the deletion tool's working directory.","solutions":["Pass the host explicitly: --host localhost:3000 (authority form: host plus non-default port).","Or export RELAY_URL=ws://localhost:3000 in the job's environment.","For cron/systemd, set the variable in the unit/job definition rather than relying on the login shell.","Prefer --host in automation — it is immune to URL-parse edge cases entirely."],"exampleFix":"# before\n./bin/run-deletion purge-old --days 30          # no RELAY_URL in env -> cannot derive community host\n# after\n./bin/run-deletion purge-old --days 30 --host localhost:3000\n# or: export RELAY_URL=ws://localhost:3000 && ./bin/run-deletion purge-old --days 30","handlingStrategy":"validation","validationCode":"# in automation, fail fast when neither route to the host exists\nif [ -z \"${RELAY_URL:-}\" ] && [ -z \"${DELETION_HOST:-}\" ]; then\n  echo 'deletion needs --host or RELAY_URL' >&2; exit 3\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass --host explicitly in cron/CI — it beats URL parsing and survives env stripping.","Define RELAY_URL in the systemd unit / job spec rather than relying on the login shell.","Document for the deletion tooling which community it is allowed to touch."],"tags":["buzz-deletion","configuration","community","cli-usage","tenant-resolution"],"backgroundTag":"missing-env-var","analyzedSha":"dad5a33865fc81a2e55b3b60746632f615ec1e3a","analyzedAt":"2026-08-20T04:38:24.874Z","contentChangedAt":"2026-08-20T04:38:24.874Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}