block/buzz · error · IngestError::Rejected

target event not found

Error message

target event not found

What it means

An 'e'-tag deletion referenced a well-formed 64-hex event id, but get_event_by_id_including_deleted() found no such event in this community — the lookup includes soft-deleted rows, so the target was never stored here (or was hard-purged). Deletions can only target events the relay actually holds; a deletion for an id the relay has never seen cannot be authorized or applied.

Source

Thrown at crates/buzz-relay/src/handlers/side_effects.rs:263

        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?
        {
            return Err(anyhow::anyhow!("must be event author"));
        }
    }

    Ok(())
}

/// Returns `true` if `actor_bytes` is the NIP-OA owner of **any** active owner-role
/// member in `members`. Used by kind:9002 and kind:9008 to authorize the owning

View on GitHub (pinned to f956e6fe06)

Solutions

  1. Verify the target id by fetching it first (POST /query or a get_event_by_id style lookup) in the same community
  2. Re-copy the id from the event you actually want deleted — compare all 64 hex chars
  3. If the target is addressable, switch to an 'a' tag deletion which authorizes by coordinate without a row lookup
  4. If testing against a fresh environment, re-publish the target event before deleting it

Example fix

// before: publish deletion for an id that was never stored here
EventBuilder::new(Kind::EventDeletion, "", [Tag::event(unknown_id)]).to_event(&keys)
// → "target event not found"

// after: confirm the event exists in this community, then delete
let hit = client.query(vec![Filter::new().id(target_id)]).await?;
assert!(!hit.is_empty(), "target not in this community");
EventBuilder::new(Kind::EventDeletion, "", [Tag::event(target_id)]).to_event(&keys)
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight each e-tag target against this community before publishing
for id in target_ids {
    let id = EventId::from_hex(&id)?;
    let exists = client.get_event_by_id(community, id).await?.is_some();
    anyhow::ensure!(exists, "target {id} not stored in this community — refusing to publish");
}

Type guard

const isWellFormedEventId = (v: string): boolean =>
  v.length === 64 && /^[0-9a-f]+$/i.test(v);

Try / catch

match validate_standard_deletion_event(&tenant, &event, &state).await {
    Err(e) if e.to_string().contains("target event not found") => {
        // drop the unknown ids from the e-tag list and re-sign once; a missing target will never appear later
        prune_missing_targets_and_republish(&event).await
    }
    other => other,
}

Prevention

When it happens

Trigger: e tag id has a typo/case error or is a truncated 64-char string; the target event lives on a different relay or in a different community (tenant fence); the event was hard-deleted by retention/purge; the id is a placeholder (all zeros) from test fixtures.

Common situations: Client fetched an id from a federated/other-community UI and tries to delete locally; copy-paste corruption of the hex id; event ids from an old environment when pointing the client at a fresh relay database.

Related errors


AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16). Data as JSON: /api/errors/68b8bc18dd807cd3. Report an issue: GitHub.