block/buzz · critical · anyhow::Error

RELAY_OWNER_PUBKEY required when…

Error message

RELAY_OWNER_PUBKEY required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true

What it means

Fatal startup error: BUZZ_REQUIRE_RELAY_MEMBERSHIP=true (NIP-43 enforcement) but no usable owner pubkey exists. config.rs silently strips an invalid RELAY_OWNER_PUBKEY (anything that is not 64-char hex) to None, and main() fails fast because a membership-enforcing relay without an owner can never be administered.

Solutions

  1. Set RELAY_OWNER_PUBKEY to the 64-char hex pubkey of the admin (no 0x, no npub, no whitespace)
  2. Verify length and charset before deploy: echo -n "$RELAY_OWNER_PUBKEY" | wc -c should be 64 and match ^[0-9a-fA-F]{64}$
  3. For local dev where you do not want enforcement, set BUZZ_REQUIRE_RELAY_MEMBERSHIP=false instead

Example fix

# before
export BUZZ_REQUIRE_RELAY_MEMBERSHIP=true
export RELAY_OWNER_PUBKEY=npub1abc...

# after
export BUZZ_REQUIRE_RELAY_MEMBERSHIP=true
export RELAY_OWNER_PUBKEY=953d1d0e0c4b7a5f6e2d8c9a1b3f5e7d9c0a2b4f6e8d0c2a4b6f8e0d2c4a6b8f
Defensive patterns

Strategy: validation

Validate before calling

# Deploy-time guard:
: "${RELAY_OWNER_PUBKEY:?RELAY_OWNER_PUBKEY required}"
[[ "$RELAY_OWNER_PUBKEY" =~ ^[0-9a-fA-F]{64}$ ]] || { echo 'RELAY_OWNER_PUBKEY must be 64-char hex'; exit 1; }

Prevention

When it happens

Trigger: Starting the relay with BUZZ_REQUIRE_RELAY_MEMBERSHIP=true while RELAY_OWNER_PUBKEY is unset, empty, contains a 0x prefix, whitespace, an npub… string, or is not exactly 64 hex characters.

Common situations: Copy-pasting an npub or a pubkey with 0x prefix from a wallet UI; CI/secret manager delivering an empty value; enabling membership enforcement on an existing deployment without adding the owner var.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of block/buzz@ef2aa1ae38 (2026-08-20). Data as JSON: /api/errors/df862e1c084b67c0. Report an issue: GitHub.

Appendix: source

Thrown at crates/buzz-relay/src/main.rs:324

        Ok(false) => {}
        Err(e) => {
            error!(
                "Replica fence disabled — floor guard verification failed: {e}. \
                 All cursor reads stay on the writer."
            );
        }
    }

    // NIP-43: if membership enforcement is on, a valid owner pubkey is required.
    // config.rs already strips invalid values with a warning; catch the resulting
    // None here so we fail fast with a clear message rather than starting a relay
    // that no one can administer.
    if config.require_relay_membership && config.relay_owner_pubkey.is_none() {
        error!(
            "BUZZ_REQUIRE_RELAY_MEMBERSHIP=true but RELAY_OWNER_PUBKEY is not set or invalid. \
             Set RELAY_OWNER_PUBKEY to a valid 64-char hex pubkey."
        );
        return Err(anyhow::anyhow!(
            "RELAY_OWNER_PUBKEY required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true"
        ));
    }

    // NIP-43: relay membership requires a stable signing key.
    // Check this before any DB mutations so we fail fast — no point backfilling
    // or bootstrapping if we'll reject the config anyway.
    if config.require_relay_membership && config.relay_private_key.is_none() {
        return Err(anyhow::anyhow!(
            "BUZZ_RELAY_PRIVATE_KEY is required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true. \
             NIP-43 events signed with an ephemeral key become unverifiable after restart."
        ));
    }

    // 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

View on GitHub (pinned to ef2aa1ae38)