block/buzz · error · anyhow::Error

failed to build '-' tag: {e}

Error message

failed to build '-' tag: {e}

What it means

buzz-admin republishes the NIP-43 membership list (kind:13534) as a protected event by parsing the literal ["-"] NIP-70 marker through nostr Tag::parse. Because the input is a compile-time constant, this error is effectively unreachable on the workspace-pinned nostr 0.44: it only fires if the nostr dependency drifted (lockfile change) to a version whose tag parser rejects the single-character '-' protected marker.

Source

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

        .get_latest_global_replaceable(
            tenant.community(),
            KIND_NIP43_MEMBERSHIP_LIST as i32,
            &relay_pubkey_bytes,
        )
        .await?
        .map(|e| e.event.created_at.as_secs());

    // custom_created_at = max(now, existing + 1s) — defeats same-second domination.
    let ts = match newest_ts {
        Some(existing) => (existing + 1).max(now),
        None => now,
    };

    let members = db.list_relay_members(tenant.community()).await?;

    let mut tags: Vec<Tag> = Vec::with_capacity(members.len() + 1);
    // NIP-70 protected-event marker — prevents re-broadcasting by third parties.
    tags.push(Tag::parse(["-"]).map_err(|e| anyhow::anyhow!("failed to build '-' tag: {e}"))?);
    for member in &members {
        tags.push(
            Tag::parse(["member", &member.pubkey, &member.role])
                .map_err(|e| anyhow::anyhow!("failed to build member tag: {e}"))?,
        );
    }

    let event = EventBuilder::new(Kind::Custom(KIND_NIP43_MEMBERSHIP_LIST as u16), "")
        .tags(tags)
        .custom_created_at(nostr::Timestamp::from(ts))
        .sign_with_keys(relay_keypair)
        .map_err(|e| anyhow::anyhow!("failed to sign kind:13534: {e}"))?;

    let (stored, was_inserted) = db
        .replace_addressable_event(tenant.community(), &event, None)
        .await?;
    if was_inserted {
        // Publish to Redis so live clients receive the updated roster.

View on GitHub (pinned to dad5a33865)

Solutions

  1. Realign nostr to the workspace pin: restore Cargo.lock or pin nostr =0.44.x and rebuild
  2. Run cargo test -p buzz-admin to confirm the membership-list publish path parses the '-' tag
  3. If it reproduces on the pinned version, file it as a nostr interop regression with the minimal Tag::parse(["-"]) repro

Example fix

# Cargo.toml
# before
nostr = "0.45"   # drifted off the workspace pin
# after
nostr = { version = "0.44", features = ["nip44", "nip98"] }
Defensive patterns

Strategy: validation

Validate before calling

# Preflight in CI: nostr stays on the workspace pin and '-' still parses
cargo tree -p buzz-admin -i nostr | head -n1
cargo test -p buzz-admin membership

Prevention

When it happens

Trigger: Building buzz-admin against a nostr version where Tag::parse(["-"]) returns Err — e.g. after a Cargo.lock regeneration picked an incompatible nostr release; the membership-list publish then bails at tag construction before signing.

Common situations: A dependency bump or cargo update -p nostr moves off the pinned 0.44 line; vendored/forked nostr builds missing NIP-70 tag support.

Related errors


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