block/buzz · error · anyhow::Error
setup-mode relay connect error: {e}
Error message
setup-mode relay connect error: {e} What it means
Setup mode's first relay interaction is HarnessRelay::connect — establish the WebSocket to BUZZ_RELAY_URL and complete the NIP-42 auth handshake with the harness key. This wrapped error means that connect failed, so setup mode exits before any subscription or watermark is attempted.
Source
Thrown at crates/buzz-acp/src/setup_mode.rs:333
);
let pubkey_hex = config.keys.public_key().to_hex();
// Parse BUZZ_AUTH_TAG for relay membership / NIP-OA.
let relay_auth_tag: Option<nostr::Tag> = std::env::var("BUZZ_AUTH_TAG")
.ok()
.filter(|s| !s.is_empty())
.and_then(|s| buzz_sdk::nip_oa::parse_auth_tag(&s).ok());
let startup_watermark: u64 = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
let mut relay =
HarnessRelay::connect(&config.relay_url, &config.keys, &pubkey_hex, relay_auth_tag)
.await
.map_err(|e| anyhow::anyhow!("setup-mode relay connect error: {e}"))?;
if let Err(e) = relay.set_startup_watermark(startup_watermark).await {
tracing::warn!("setup-mode: failed to set startup watermark: {e}");
}
relay
.subscribe_membership_notifications()
.await
.map_err(|e| anyhow::anyhow!("setup-mode membership subscribe error: {e}"))?;
tracing::info!("setup-mode: connected and subscribed to membership notifications");
let rest_client = relay.rest_client();
let mut author_gate_ctx =
crate::InboundAuthorGate::connect(&rest_client, &pubkey_hex, "setup startup").await;
// Resolve owner for author-gate (same priority as normal mode).
let startup_owner = crate::resolve_agent_owner(&config);View on GitHub (pinned to dad5a33865)
Solutions
- Confirm the relay is running and the URL scheme is explicit: ws://localhost:3000 or wss://host
- Check the harness env: BUZZ_RELAY_URL, BUZZ_PRIVATE_KEY, relay auth tag
- Test reachability independently (curl the relay's HTTP NIP-11 endpoint on the same host)
- Retry after the relay is healthy
Example fix
# before export BUZZ_RELAY_URL=localhost:3000 # after export BUZZ_RELAY_URL=ws://localhost:3000
Defensive patterns
Strategy: retry
Validate before calling
#!/usr/bin/env bash
: "${BUZZ_RELAY_URL:?BUZZ_RELAY_URL required for setup mode}"
case "$BUZZ_RELAY_URL" in ws://*|wss://*) ;; *) echo "BUZZ_RELAY_URL must start with ws:// or wss://" >&2; exit 1;; esac
nc -z "$(echo "$BUZZ_RELAY_URL" | sed -E 's|^wss?://||; s|:[0-9]+$||')" "$(echo "$BUZZ_RELAY_URL" | sed -nE 's|.*:([0-9]+)$|\1|p')" \
|| { echo 'relay port not reachable' >&2; exit 1; } Try / catch
// Retry transient connect failures; fail fast on auth-shaped ones
loop {
match HarnessRelay::connect(&url, &keys, &pubkey, auth_tag).await {
Err(e) if is_auth_error(&e) => return Err(e), // do not retry bad credentials
Err(_) if attempts < MAX => { backoff.wait().await; }
other => return other.map(|_| ()),
}
} Prevention
- Start the relay (just relay) before any setup-mode onboarding run
- Keep BUZZ_RELAY_URL schemed (ws:// or wss://) in all environments; rotate auth tags together with the harness deployment
When it happens
Trigger: BUZZ_RELAY_URL wrong (typo, missing ws:// or wss:// scheme), relay not running or unreachable, TLS failure on wss://, or the auth handshake rejected due to an invalid/expired auth tag.
Common situations: Local relay not started (just relay missing from the workflow); staging URL changed; auth tag env rotated while the harness kept the old value; firewall/proxy blocking the WebSocket upgrade.
Related errors
- setup-mode membership subscribe error: {e}
- setup-mode channel discovery error: {e}
- observer control subscribe error: {e}
- malformed {SETUP_PAYLOAD_ENV_VAR}: {e}
- channel discovery error: {e}
AI-assisted analysis of block/buzz@dad5a33865 (2026-08-20).
Data as JSON: /api/errors/df1db88f87f3a38d.
Report an issue: GitHub.