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
- Realign nostr to the workspace pin: restore Cargo.lock or pin nostr =0.44.x and rebuild
- Run cargo test -p buzz-admin to confirm the membership-list publish path parses the '-' tag
- 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
- Commit Cargo.lock and review it in PRs; a silent nostr bump is the only realistic path to this error
- Keep a unit test asserting nostr::Tag::parse(["-"]).is_ok() so parser regressions fail at build time, not during an admin publish
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
- failed to build member tag: {e}
- failed to sign kind:13534: {e}
- invalid BUZZ_RELAY_PRIVATE_KEY: {e}
- invalid relay key: {e}
- sign kind:39000: {e}
AI-assisted analysis of block/buzz@dad5a33865 (2026-08-20).
Data as JSON: /api/errors/33d6005beb943374.
Report an issue: GitHub.