block/buzz · error · IngestError::Rejected
must be event author
Error message
must be event author
What it means
For an 'a'-tag deletion: the coordinate's publisher pubkey is not the deletion's effective author, and is_agent_owner() reports the signer does not own that agent pubkey in this community. Buzz extends NIP-09 so a human may delete their own agent's addressable events (NIP-OA ownership), but a third party deleting someone else's coordinate is refused. Note effective_message_author() unwraps relay-signed attribution (actor/p tags) before comparing.
Source
Thrown at crates/buzz-relay/src/handlers/side_effects.rs:253
let a_tag = event
.tags
.iter()
.find(|t| t.kind().to_string() == "a")
.and_then(|t| t.content().map(|s| s.to_string()))
.ok_or_else(|| anyhow::anyhow!("missing e or a tag for target"))?;
let parts: Vec<&str> = a_tag.splitn(3, ':').collect();
if parts.len() < 2 {
return Err(anyhow::anyhow!("invalid a-tag format"));
}
let target_pubkey_bytes =
hex::decode(parts[1]).map_err(|_| anyhow::anyhow!("invalid pubkey in a-tag"))?;
if target_pubkey_bytes != actor_bytes
&& !state
.db
.is_agent_owner(tenant.community(), &target_pubkey_bytes, &actor_bytes)
.await?
{
return Err(anyhow::anyhow!("must be event author"));
}
return Ok(());
}
for target_id in target_ids {
let target_event = state
.db
.get_event_by_id_including_deleted(tenant.community(), &target_id)
.await?
.ok_or_else(|| anyhow::anyhow!("target event not found"))?;
let target_author =
effective_message_author(&target_event.event, &state.relay_keypair.public_key());
if target_author != actor_bytes
&& !state
.db
.is_agent_owner(tenant.community(), &target_author, &actor_bytes)
.await?View on GitHub (pinned to f956e6fe06)
Solutions
- Sign the deletion with the same key that published the addressable event (the coordinate's pubkey)
- If the coordinate belongs to your agent, ensure the agent-owner relationship is registered in this community (is_agent_owner must match), then sign with the owner key
- If you are a channel admin deleting someone else's content, use kind 9005 (channel admin deletion) instead of kind 5
- Check the coordinate string is not stale — republished events may live under a different pubkey than an earlier version
Example fix
// before: owner key deletes coordinate published by unrelated key
// a = "30078:<other-pubkey>:general" signed by <my-key> → must be event author
// after: sign with the coordinate's own publisher key
let keys = Keys::from(...); // the key whose hex == parts[1]
EventBuilder::new(Kind::EventDeletion, "", [Tag::custom(TagKind::Custom("a"), vec![a])])
.to_event(&keys) Defensive patterns
Strategy: validation
Validate before calling
// Before publishing an a-tag deletion, confirm the coordinate's pubkey is yours // (or an agent you own in this community) let parts: Vec<&str> = a_value.splitn(3, ':').collect(); let coord_pk = hex::decode(parts[1])?; let mine = coord_pk == signing_keys.public_key().to_bytes().to_vec(); let my_agent = client.is_agent_owner(community, coord_pk, signing_keys.public_key()).await?; anyhow::ensure!(mine || my_agent, "cannot delete a coordinate you do not own");
Type guard
fn owns_coordinate(signer_pk: &[u8], coord: &str) -> bool {
coord
.splitn(3, ':')
.nth(1)
.and_then(|p| hex::decode(p).ok())
.map(|p| p == signer_pk)
.unwrap_or(false)
} Try / catch
match validate_standard_deletion_event(&tenant, &event, &state).await {
Err(e) if e.to_string().contains("must be event author") && a_tag_path => {
// pick the key that published the coordinate (or register agent ownership) — do not retry blindly
prompt_switch_identity(&event);
}
other => other,
} Prevention
- Track which key published each addressable event and select that key when building deletions
- Register NIP-OA agent ownership at agent provisioning time so the owner can always clean up
- Moderators deleting others' content must use kind 9005, never kind 5 — encode this in tooling
When it happens
Trigger: Deleting an addressable event whose coordinate names another user's pubkey; signing the deletion with a fresh key instead of the key that published the coordinate; a human deleting an agent's event without the NIP-OA agent-owner registration linking them in this community.
Common situations: Rotated keys after republishing under a new pubkey; agent events published under the agent key but the owner relationship was never registered via the agent-owner path; deleting across communities — ownership rows are tenant-scoped.
Related errors
- missing e or a tag for target
- invalid a-tag format
- target event not found
- moderator access required
- invalid pubkey in a-tag
AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16).
Data as JSON: /api/errors/3157ed73318f04cf.
Report an issue: GitHub.