{"record":{"id":"0e806916c837fdbe","repo":"block/buzz","slug":"channel-requires-relay-key-or-buzz-relay-priva","errorCode":null,"errorMessage":"--channel requires --relay-key or BUZZ_RELAY_PRIVATE_KEY","messagePattern":"--channel requires --relay-key or BUZZ_RELAY_PRIVATE_KEY","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/buzz-admin/src/main.rs","lineNumber":489,"sourceCode":"    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\n    // Resolve relay signing key: arg > env > ephemeral. Force-republish must\n    // never use an ephemeral key because it replaces an existing authoritative\n    // snapshot.\n    let configured_relay_key =\n        relay_key_arg.or_else(|| std::env::var(\"BUZZ_RELAY_PRIVATE_KEY\").ok());\n    if channel_arg.is_some() && configured_relay_key.is_none() {\n        return Err(anyhow::anyhow!(\n            \"--channel requires --relay-key or BUZZ_RELAY_PRIVATE_KEY\"\n        ));\n    }\n    let relay_keys = match configured_relay_key {\n        Some(key_hex) => {\n            Keys::parse(&key_hex).map_err(|e| anyhow::anyhow!(\"invalid relay key: {e}\"))?\n        }\n        None => {\n            let k = Keys::generate();\n            eprintln!(\n                \"Warning: no relay key provided — using ephemeral key {}\",\n                k.public_key().to_hex()\n            );\n            eprintln!(\"Events signed with this key won't be verifiable after this run.\");\n            eprintln!(\"Pass --relay-key or set BUZZ_RELAY_PRIVATE_KEY for production use.\");\n            k\n        }\n    };","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-admin/src/main.rs#L471-L507","documentation":"reconcile_channels() refuses to run in --channel (single-channel force-republish) mode without a signing key. Reconciling one specific channel replaces that channel's existing authoritative kind:39000/39001/39002 snapshot events, so it must be signed by the same stable relay key as the originals — an ephemeral key would silently orphan the snapshot. The key can come from the --relay-key argument or BUZZ_RELAY_PRIVATE_KEY; if neither is present alongside --channel, this error fires. Without --channel, the command proceeds with a warning and an ephemeral key (acceptable for backfilling channels that have no events yet).","triggerScenarios":"`buzz-admin reconcile-channels --channel <uuid>` with neither --relay-key nor BUZZ_RELAY_PRIVATE_KEY in the environment. Typical when an operator escalates from a full reconcile (which tolerated the ephemeral-key warning) to a targeted re-publish of one channel without adding a key.","commonSituations":"Recovery playbooks that say 're-run reconcile for channel X' but were written assuming the env var was already exported; running from a clean CI shell where only DATABASE_URL/RELAY_URL are set.","solutions":["Pass the relay's signing key explicitly: `buzz-admin reconcile-channels --channel <uuid> --relay-key <64-hex-or-nsec>` (use the SAME key the relay signs with).","Or export BUZZ_RELAY_PRIVATE_KEY=<relay secret key> in the shell and re-run the command unchanged.","If you only meant to backfill channels that have no events yet, drop --channel and run a full reconcile — the ephemeral-key path is allowed there (it prints a warning)."],"exampleFix":"# before\nbuzz-admin reconcile-channels --channel 6f9c...\n# error: --channel requires --relay-key or BUZZ_RELAY_PRIVATE_KEY\n\n# after\nbuzz-admin reconcile-channels --channel 6f9c... --relay-key $BUZZ_RELAY_PRIVATE_KEY","handlingStrategy":"validation","validationCode":"# force-republish path requires a key: check flag/env pairing before invoking\nif [ \"$1\" = \"--channel\" ] || [[ \"$*\" == *--channel* ]]; then\n  [ -n \"${BUZZ_RELAY_PRIVATE_KEY:-}\" ] || { echo 'pass --relay-key or set BUZZ_RELAY_PRIVATE_KEY' >&2; exit 1; }\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize on always exporting BUZZ_RELAY_PRIVATE_KEY for admin shells so --channel never trips the guard.","Document that force-republish (single channel) requires the relay's real key — never a generated one."],"tags":["buzz-admin","cli-arguments","reconcile","signing-key","validation"],"backgroundTag":"missing-required-parameter","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}