{"record":{"id":"33d6005beb943374","repo":"block/buzz","slug":"failed-to-build-tag-e","errorCode":null,"errorMessage":"failed to build '-' tag: {e}","messagePattern":"failed to build '-' tag: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/buzz-admin/src/main.rs","lineNumber":362,"sourceCode":"        .get_latest_global_replaceable(\n            tenant.community(),\n            KIND_NIP43_MEMBERSHIP_LIST as i32,\n            &relay_pubkey_bytes,\n        )\n        .await?\n        .map(|e| e.event.created_at.as_secs());\n\n    // custom_created_at = max(now, existing + 1s) — defeats same-second domination.\n    let ts = match newest_ts {\n        Some(existing) => (existing + 1).max(now),\n        None => now,\n    };\n\n    let members = db.list_relay_members(tenant.community()).await?;\n\n    let mut tags: Vec<Tag> = Vec::with_capacity(members.len() + 1);\n    // NIP-70 protected-event marker — prevents re-broadcasting by third parties.\n    tags.push(Tag::parse([\"-\"]).map_err(|e| anyhow::anyhow!(\"failed to build '-' tag: {e}\"))?);\n    for member in &members {\n        tags.push(\n            Tag::parse([\"member\", &member.pubkey, &member.role])\n                .map_err(|e| anyhow::anyhow!(\"failed to build member tag: {e}\"))?,\n        );\n    }\n\n    let event = EventBuilder::new(Kind::Custom(KIND_NIP43_MEMBERSHIP_LIST as u16), \"\")\n        .tags(tags)\n        .custom_created_at(nostr::Timestamp::from(ts))\n        .sign_with_keys(relay_keypair)\n        .map_err(|e| anyhow::anyhow!(\"failed to sign kind:13534: {e}\"))?;\n\n    let (stored, was_inserted) = db\n        .replace_addressable_event(tenant.community(), &event, None)\n        .await?;\n    if was_inserted {\n        // Publish to Redis so live clients receive the updated roster.","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/block/buzz/blob/dad5a33865fc81a2e55b3b60746632f615ec1e3a/crates/buzz-admin/src/main.rs#L344-L380","documentation":"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.","triggerScenarios":"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.","commonSituations":"A dependency bump or cargo update -p nostr moves off the pinned 0.44 line; vendored/forked nostr builds missing NIP-70 tag support.","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"],"exampleFix":"# Cargo.toml\n# before\nnostr = \"0.45\"   # drifted off the workspace pin\n# after\nnostr = { version = \"0.44\", features = [\"nip44\", \"nip98\"] }","handlingStrategy":"validation","validationCode":"# Preflight in CI: nostr stays on the workspace pin and '-' still parses\ncargo tree -p buzz-admin -i nostr | head -n1\ncargo test -p buzz-admin membership","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["buzz-admin","nostr","nip-70","tags","dependency-drift"],"backgroundTag":"tag-parse-failed","analyzedSha":"dad5a33865fc81a2e55b3b60746632f615ec1e3a","analyzedAt":"2026-08-20T04:38:24.874Z","contentChangedAt":"2026-08-20T04:38:24.874Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}