block/buzz · error

invalid BUZZ_RELAY_PRIVATE_KEY: {e}

Error message

invalid BUZZ_RELAY_PRIVATE_KEY: {e}

What it means

connect_member_services() found BUZZ_RELAY_PRIVATE_KEY but nostr's Keys::parse() rejected it. Keys::parse accepts a 64-char hex secret key or a bech32 nsec1… string; the error means the value does not decode to a valid secp256k1 secret key (wrong length, non-hex characters, 0x-prefixed hex, or a corrupted/placeholder value). The underlying parse error is appended as {e}.

Source

Thrown at crates/buzz-admin/src/main.rs:412

        "NIP-43 membership list published by buzz-admin"
    );
    Ok(())
}

/// Connect to DB, Redis pub/sub, and load the relay keypair.
///
/// `BUZZ_RELAY_PRIVATE_KEY` is required — the CLI signs kind:13534 events.
async fn connect_member_services() -> Result<(Db, Arc<PubSubManager>, Keys)> {
    let db = connect_db().await?;

    let relay_keypair = {
        let hex = std::env::var("BUZZ_RELAY_PRIVATE_KEY").map_err(|_| {
            anyhow::anyhow!(
                "BUZZ_RELAY_PRIVATE_KEY is required for add-member/remove-member.\n\
                 The relay must have a stable signing key to publish kind:13534 events."
            )
        })?;
        Keys::parse(&hex).map_err(|e| anyhow::anyhow!("invalid BUZZ_RELAY_PRIVATE_KEY: {e}"))?
    };

    let redis_url =
        std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://localhost:6379".to_string());

    let redis_pool = {
        let cfg = deadpool_redis::Config::from_url(&redis_url);
        cfg.create_pool(Some(deadpool_redis::Runtime::Tokio1))
            .map_err(|e| anyhow::anyhow!("Redis pool creation failed: {e}"))?
    };

    let pubsub = Arc::new(
        PubSubManager::new(&redis_url, redis_pool)
            .await
            .map_err(|e| anyhow::anyhow!("PubSub init failed: {e}"))?,
    );

    Ok((db, pubsub, relay_keypair))

View on GitHub (pinned to f956e6fe06)

Solutions

  1. Verify the value is exactly 64 hex characters (or a well-formed nsec1… bech32 string) with no whitespace, quotes, or 0x prefix: `echo -n "$BUZZ_RELAY_PRIVATE_KEY" | wc -c` should print 64.
  2. Confirm it starts with a hex secret, not npub1… — npub is the PUBLIC key and cannot sign; the relay's own config/secret store has the matching nsec/hex secret.
  3. Re-copy the exact value from the relay's configuration (the same key the relay signs with), then re-run the subcommand.
  4. Sanity-check it parses standalone before retrying: `python3 -c "import sys; bytes.fromhex(sys.argv[1])" "$BUZZ_RELAY_PRIVATE_KEY"` (or any hex validator).

Example fix

# before: npub (public key) mistakenly used
BUZZ_RELAY_PRIVATE_KEY=npub1abcdef...

# after: 64-char hex secret key
BUZZ_RELAY_PRIVATE_KEY=8i0j...64-hex-chars... (exact secret the relay process uses)
Defensive patterns

Strategy: validation

Validate before calling

# reject before running the CLI: must be 64 hex chars (or a valid nsec1 string)
key="${BUZZ_RELAY_PRIVATE_KEY:-}"
if ! [[ "$key" =~ ^[0-9a-fA-F]{64}$ ]]; then
  echo "BUZZ_RELAY_PRIVATE_KEY must be 64 hex chars (got ${#key})" >&2
  exit 1
fi

Prevention

When it happens

Trigger: BUZZ_RELAY_PRIVATE_KEY is set to a public key (npub1…/66 hex chars) instead of the secret, has a 0x prefix, contains a trailing newline/quote from a .env copy, or is a bech32 nsec with a typo. Any add-member/remove-member invocation then fails after DB connect but before signing.

Common situations: Copy-pasting the relay's PUBLIC key into the env var; shell quoting mistakes (value captured with quotes `"abc"`); values read via `grep | cut` that include whitespace or CRLF from a Windows-edited .env; using a truncated 63-char hex key.

Related errors


AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16). Data as JSON: /api/errors/18a6ef2bf2c36ea8. Report an issue: GitHub.