block/buzz · error · anyhow::Error
project announcement is missing its address
Error message
project announcement is missing its address
What it means
Every project announcement template must carry a d tag with a non-empty value: the d tag is the NIP-33 address coordinate (kind:pubkey:d) that makes the announcement replaceable and resolvable. A template with no d tag, or one whose value is empty or whitespace-only, is rejected before signing.
Source
Thrown at crates/buzz-acp/src/lib.rs:1722
});
}
fn build_project_owner_announcement_events(
announcements: Vec<ProjectOwnerAnnouncementTemplate>,
keys: &nostr::Keys,
) -> Result<Vec<nostr::Event>> {
let now = nostr::Timestamp::now().as_secs();
announcements
.into_iter()
.map(|template| {
if !matches!(template.kind, 30_617 | 30_621) {
anyhow::bail!("unsupported project announcement kind");
}
if !template.tags.iter().any(|tag| {
tag.first().is_some_and(|value| value == "d")
&& tag.get(1).is_some_and(|value| !value.trim().is_empty())
}) {
anyhow::bail!("project announcement is missing its address");
}
let tags = template
.tags
.into_iter()
.map(|tag| {
nostr::Tag::parse(tag)
.map_err(|error| anyhow::anyhow!("invalid project tag: {error}"))
})
.collect::<Result<Vec<_>>>()?;
let created_at = template.created_at.unwrap_or(now);
if created_at > now.saturating_add(300) {
anyhow::bail!("project announcement timestamp is too far in the future");
}
nostr::EventBuilder::new(nostr::Kind::Custom(template.kind), template.content)
.tags(tags)
.custom_created_at(nostr::Timestamp::from(created_at))
.sign_with_keys(keys)
.map_err(|error| anyhow::anyhow!("sign project announcement: {error}"))View on GitHub (pinned to dad5a33865)
Solutions
- Add a d tag with a stable, non-empty identifier: [["d", "my-project"]]
- Keep the d value stable across restarts so the announcement replaces (NIP-33 LWW) instead of duplicating
- Validate the template JSON with a preflight check before deploying the harness
Example fix
# agent config
# before
project_owner_announcements:
- kind: 30621
tags: [["name", "my-project"]]
# after
project_owner_announcements:
- kind: 30621
tags: [["d", "my-project"], ["name", "my-project"]] Defensive patterns
Strategy: validation
Validate before calling
// Preflight: every template must carry a non-empty d tag
let ok = templates.iter().all(|t| {
t.tags.iter().any(|tag| {
tag.first().is_some_and(|k| k == "d")
&& tag.get(1).is_some_and(|v| !v.trim().is_empty())
})
});
if !ok { anyhow::bail!("a project announcement template is missing its d tag"); } Type guard
fn has_address_tag(tags: &[Vec<String>]) -> bool {
tags.iter().any(|tag| {
tag.first().is_some_and(|k| k == "d")
&& tag.get(1).is_some_and(|v| !v.trim().is_empty())
})
} Prevention
- Remember NIP-33 addressable events live at kind:pubkey:d — a missing d tag makes them unreplaceable
- Keep the d value stable across config regenerations to avoid duplicate announcements
When it happens
Trigger: A project_owner_announcements template whose tags array lacks a ["d", "..."] entry entirely, or contains ["d", ""] / ["d", " "]; the check at crates/buzz-acp/src/lib.rs:1220-1224 fails during event construction at startup.
Common situations: Hand-written config where the author assumed the id field was enough; a template generator that emits tags only for members and forgets the address tag.
Related errors
- unsupported project announcement kind
- project announcement timestamp is too far in the future
- kind:30617 missing d tag
- invalid repo identifier: must be [a-zA-Z0-9._-]{1,64}, no le
- moderation notice recipient must be a 32-byte pubkey, got {}
AI-assisted analysis of block/buzz@dad5a33865 (2026-08-20).
Data as JSON: /api/errors/3440ad729e24269c.
Report an issue: GitHub.