block/buzz · error
delete failed: {e}
Error message
delete failed: {e} What it means
This error wraps a database failure from `execute_delete_with_marker` during the "delete" enforcement action of report resolution (`run_atomic_mutation`). The atomic mutation tries to delete the reported event and set the action's step_marker in one lease-fenced transaction; if the DB layer returns any error (connection issue, constraint violation, row gone), it is re-wrapped with the "delete failed: {e}" context and propagated up through `drive_enforcement`. The inner `{e}` carries the actual Postgres/DB-layer cause.
Source
Thrown at crates/buzz-relay/src/handlers/report_resolution.rs:771
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}")),
};
match raw? {
true => Ok(MutationOutcome::Committed),
false => {
// Reload to distinguish "step_marker already set by another driver"
// (AlreadyCommitted — safe to proceed to finalization) from "this
// driver's lease expired" (LeaseLost — must stop, recovery worker
// will take over after expiry).
let rec = state
.db
.get_admin_action(action_id)
.await
.map_err(|e| anyhow::anyhow!("classify mutation result: {e}"))?;
match rec {
Some(r) if r.step_marker.is_some() => Ok(MutationOutcome::AlreadyCommitted),View on GitHub (pinned to eed74bde2f)
Solutions
- Check the inner `{e}` message to identify the actual DB-layer cause (connectivity vs constraint vs serialization) and fix that root problem.
- Verify Postgres connectivity/health of the relay's database pool (connections, timeouts, restarts).
- Retry the action after the lease expires — the action recovery worker will re-drive the mutation; the lease-fenced marker makes retries safe.
- If a constraint violation on parent/root, inspect `thread_metadata` rows for the target event and confirm parent/root ids match the live thread state.
- Check relay logs around `drive_enforcement` for whether `raw?` failed at the mutation or the later classification step.
Example fix
// before: raw anyhow error from DB layer bubbles with no context
.execute_delete_with_marker(...).await?;
// after: context-wrapped (as thrown) — fix at call site by matching recoverable DB errors
let deleted = state.db.execute_delete_with_marker(...).await
.map_err(|e| anyhow::anyhow!("delete failed: {e}"));
match deleted {
Ok(v) => Ok(v),
Err(e) if is_transient_db_error(&e) => Ok(false), // let recovery worker re-drive
Err(e) => Err(anyhow::anyhow!("delete failed: {e}")),
} Defensive patterns
Strategy: retry
Validate before calling
// before driving: confirm target event still exists and DB is reachable
let meta = state.db.get_thread_metadata_by_event(ctx.community_id, target).await
.map_err(|e| anyhow::anyhow!("pre-check thread metadata: {e}"))?;
if is_transient_db_error(&e) { schedule_retry_after_lease_expiry(action_id); } Type guard
fn is_transient_db_error(e: &anyhow::Error) -> bool {
let s = format!("{e:#}");
["connection", "timeout", "closed", "pool"].iter().any(|k| s.contains(k))
} Try / catch
match run_atomic_mutation(ctx).await {
Ok(outcome) => proceed_with_finalization(outcome),
Err(e) if is_transient_db_error(&e) => log_and_defer_to_recovery_worker(ctx.action_id, e),
Err(e) => return Err(e), // permanent: surface to moderator
} Prevention
- Rely on the lease-fenced marker design: failed deletes are safe to re-drive after lease expiry — prefer deferral over inline retry loops.
- Monitor Postgres health and connection-pool saturation on the relay.
- Keep thread_metadata (parent/root ids) consistent before issuing delete enforcement.
- Alert on 'delete failed' log lines to catch DB degradation early.
When it happens
Trigger: Calling resolve/enforcement flow where ctx.action == "delete" and `execute_delete_with_marker(action_id, lease_token, community_id, target_event_id, parent_id, root_id)` returns Err — e.g. Postgres connection dropped, deadlock, the target event row violating a FK during deletion, or a transaction failure inside the lease-fenced marker update.
Common situations: Relay DB briefly unavailable or failing over while a moderator resolves a report with 'delete content'; recovery worker re-driving an action against a DB under lock contention; parent/root thread metadata rows being concurrently mutated causing FK conflicts during thread-aware delete.
Related errors
- ban failed: {e}
- timeout failed: {e}
- system message insert failed: {e}
- ban requires target_pubkey
- timeout requires target_pubkey
AI-assisted analysis of block/buzz@eed74bde2f (2026-08-30).
Data as JSON: /api/errors/c58f929017f39c2c.
Report an issue: GitHub.