block/buzz · error
thread metadata lookup failed: {e}
Error message
thread metadata lookup failed: {e} What it means
Before deleting the target event, `run_atomic_mutation` calls `get_thread_metadata_by_event` to look up the thread's parent/root ids (used to update thread counters), and that query failed with a database error, wrapped as `thread metadata lookup failed: {e}`. This is a DB-layer failure, not a business-logic rejection — the delete itself never ran.
Source
Thrown at crates/buzz-relay/src/handlers/report_resolution.rs:757
.await
.map_err(|e| anyhow::anyhow!("kick failed: {e}"))?
{
buzz_db::relay_admin_actions::KickWithMarkerResult::Removed => Ok(true),
buzz_db::relay_admin_actions::KickWithMarkerResult::AlreadyMarked => Ok(false),
buzz_db::relay_admin_actions::KickWithMarkerResult::AlreadyGone => Err(
anyhow::anyhow!("kick target was already absent before this action"),
),
}
}
"delete" => {
let target = ctx
.target_event_id
.ok_or_else(|| anyhow::anyhow!("delete requires target_event_id"))?;
let meta = state
.db
.get_thread_metadata_by_event(ctx.community_id, target)
.await
.map_err(|e| anyhow::anyhow!("thread metadata lookup failed: {e}"))?;
let parent_id = meta.as_ref().and_then(|m| m.parent_event_id.clone());
let root_id = meta.as_ref().and_then(|m| m.root_event_id.clone());
state
.db
.execute_delete_with_marker(
action_id,
lease_token,
ctx.community_id,
target,
parent_id.as_deref(),
root_id.as_deref(),
)
.await
.map_err(|e| anyhow::anyhow!("delete failed: {e}"))
}
other => Err(anyhow::anyhow!("unexpected enforcement action: {other}")),
};
View on GitHub (pinned to eed74bde2f)
Solutions
- Read the wrapped `{e}` in relay logs to identify the exact Postgres error (connection, timeout, relation-not-found).
- For relation/column errors: run pending migrations and restart the relay so schema matches the binary.
- For timeouts/pool exhaustion: raise pool size or statement timeout, and retry — enforcement is idempotent and re-drivable.
- Confirm the event id passed to `get_thread_metadata_by_event` is well-formed (32-byte binary) and not truncated upstream.
Example fix
// before
let meta = state.db.get_thread_metadata_by_event(ctx.community_id, target)
.await
.map_err(|e| anyhow::anyhow!("thread metadata lookup failed: {e}"))?;
// after
let meta = match state.db.get_thread_metadata_by_event(ctx.community_id, target).await {
Ok(m) => m,
Err(e) if is_transient(&e) => {
tokio::time::sleep(Duration::from_millis(200)).await;
state.db.get_thread_metadata_by_event(ctx.community_id, target).await
.map_err(|e| anyhow::anyhow!("thread metadata lookup failed: {e}"))?
}
Err(e) => return Err(anyhow::anyhow!("thread metadata lookup failed: {e}")),
}; Defensive patterns
Strategy: retry
Validate before calling
// verify the target event exists before driving a delete let exists = state.db.event_exists(community_id, target_event_id).await?; anyhow::ensure!(exists, "target event not found in community; skip delete");
Type guard
fn is_transient_db_err(e: &anyhow::Error) -> bool {
let s = e.to_string();
s.contains("connection") || s.contains("timeout") || s.contains("pool")
} Try / catch
match run_atomic_mutation(state, action_id, lease_token, &ctx).await {
Err(e) if is_transient_db_err(&e) => schedule_retry(action_id, backoff()),
Err(e) if e.to_string().contains("thread metadata lookup failed") => {
alert_schema_drift_or_db_health(action_id, e);
}
other => other?,
} Prevention
- Run `just test` (Postgres-backed) after touching buzz-db or migration files.
- Confirm migrations are applied whenever the relay binary is upgraded.
- Monitor Postgres health (pool saturation, statement timeouts) around enforcement workers.
- Log the wrapped inner DB error verbatim — the message alone hides the root cause.
When it happens
Trigger: 1) Postgres connection failure, pool exhaustion, or statement timeout while reading thread metadata. 2) Schema drift: the thread-metadata table/columns expected by the query are missing (failed migration). 3) Malformed `target_event_id` causing a query/decode error at the DB layer rather than a clean `None`.
Common situations: Relay under heavy load with a saturated connection pool; a half-applied migration after upgrading the relay binary; disk/network issues between relay and Postgres in containerized deployments (e.g. the staging Kubernetes setup).
Related errors
AI-assisted analysis of block/buzz@eed74bde2f (2026-08-30).
Data as JSON: /api/errors/e91dbe4a1d0c2d03.
Report an issue: GitHub.