block/buzz · error · IngestError::Rejected
channel not found
Error message
channel not found
What it means
get_channel() for the h-tag UUID failed and the error is mapped to "channel not found" — the UUID does not resolve to a channel in this community (and note the map_err also folds genuine DB failures into this message). Admin-event validation happens before storage, so the mutation is rejected up front. Cross-community UUIDs never resolve because the lookup is fenced to tenant.community().
Source
Thrown at crates/buzz-relay/src/handlers/side_effects.rs:328
) -> anyhow::Result<()> {
// CREATE_GROUP doesn't need an existing channel — skip h-tag extraction
if kind == 9007 {
return Ok(());
}
// Extract channel from h tag
let channel_id =
extract_h_tag_channel(event).ok_or_else(|| anyhow::anyhow!("missing or invalid h tag"))?;
let actor_bytes = event.pubkey.to_bytes().to_vec();
// Reject mutations on archived channels — except kind:9002 with archived=false
// (unarchive), which must be allowed through so the channel can be restored.
let channel = state
.db
.get_channel(tenant.community(), channel_id)
.await
.map_err(|_| anyhow::anyhow!("channel not found"))?;
let is_unarchive_request = kind == 9002
&& event.tags.iter().any(|t| {
let parts = t.as_slice();
parts.len() >= 2 && parts[0] == "archived" && parts[1] == "false"
});
if channel.archived_at.is_some() && !is_unarchive_request {
return Err(anyhow::anyhow!("channel is archived"));
}
match kind {
9000 => {
// An absent role tag means "no role change requested": for an existing
// member that preserves the role they already hold, and only defaults
// to Member for a genuinely new member. Defaulting unconditionally to
// Member made a bare self-targeted PUT_USER silently demote an owner.
let role_str = extract_tag_value(event, "role");
let requested_role = match role_str {
Some(ref s) => match s.parse::<buzz_db::channel::MemberRole>() {View on GitHub (pinned to f956e6fe06)
Solutions
- Re-list channels for the community and copy the exact UUID into the h tag
- If the channel was deleted, recreate it (kind 9007) before issuing further admin events
- Check relay logs/DB health — a real database error is reported through this same message, so verify connectivity before assuming the UUID is wrong
- In tests, create the channel first and use the returned id, never a fabricated UUID
Example fix
// before: fabricated/stale UUID let h = "00000000-0000-0000-0000-000000000000".to_string(); // after: resolve the real channel id let channels = client.get_channels().await?; let h = channels.iter().find(|c| c.name == "general").unwrap().id.to_string();
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the channel exists in this community before mutating it
let channel = client.get_channel(community, channel_uuid).await;
match channel {
Ok(ch) => ch,
Err(_) => anyhow::bail!("channel {channel_uuid} not found — refresh channel list"),
} Try / catch
match validate_admin_event(&tenant, kind, &event, &state).await {
Err(e) if e.to_string().contains("channel not found") => {
// Do not retry with the same UUID; refresh the channel list and re-target.
// Also check DB health — real DB errors surface through this same message.
refresh_channels_and_abort(&event)
}
other => other,
} Prevention
- Cache channel UUIDs with a TTL and re-resolve when an admin event fails validation
- Never hand-type UUIDs into events; copy from a channels-list API response
- Treat a burst of these errors across many channels as a possible DB outage, not bad ids
When it happens
Trigger: h tag carries a UUID from a different community/relay or a stale/deleted channel; UUID typo (swapped digits still parse but match nothing); the channel was hard-deleted after a kind 9008 delete; the database is unreachable and the DB error is masked as not-found.
Common situations: Copied channel UUID from another environment (staging → prod); client cached an old channel list; concurrent delete racing a later admin event; using a random/generated UUID in tests without creating the channel first.
Related errors
- missing or invalid h tag
- channel is archived
- missing p tag
- actor not authorized
- only owners/admins may grant elevated roles
AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16).
Data as JSON: /api/errors/0a871b4d14f08b94.
Report an issue: GitHub.