block/buzz · error
timeout failed: {e}
Error message
timeout failed: {e} What it means
The 'timeout' arm of `run_atomic_mutation` wraps any failure from `state.db.execute_timeout_with_marker` with 'timeout failed: {e}'. The context was complete (target and expiry present), but the database-side timeout operation failed, and the error is re-wrapped for the enforcement driver's bookkeeping.
Source
Thrown at crates/buzz-relay/src/handlers/report_resolution.rs:720
let target = ctx
.target_pubkey
.ok_or_else(|| anyhow::anyhow!("timeout requires target_pubkey"))?;
let until = ctx
.timeout_until
.ok_or_else(|| anyhow::anyhow!("timeout requires timeout_until"))?;
state
.db
.execute_timeout_with_marker(
action_id,
lease_token,
ctx.community_id,
target,
ctx.actor_pubkey,
until,
ctx.reason,
)
.await
.map_err(|e| anyhow::anyhow!("timeout failed: {e}"))
}
"kick" => {
let target = ctx
.target_pubkey
.ok_or_else(|| anyhow::anyhow!("kick requires target_pubkey"))?;
let ch = ctx
.channel_id
.ok_or_else(|| anyhow::anyhow!("kick requires channel_id"))?;
match state
.db
.execute_kick_with_marker(
action_id,
lease_token,
ctx.community_id,
ch,
target,
ctx.actor_pubkey,
)View on GitHub (pinned to eed74bde2f)
Solutions
- Inspect the inner `{e}` message in the error chain for the concrete DB cause.
- Treat lease/marker conflicts as 'already applied' — the atomic marker makes timeouts idempotent per action_id.
- Check Postgres availability and schema migrations; run `just test` integration suite to reproduce locally.
- Retry the driver on transient errors; skip actions whose marker shows another driver completed them.
Example fix
// before
execute_timeout_with_marker(...).await.map_err(|e| anyhow!("timeout failed: {e}"))
// after — tolerate already-applied marker
match execute_timeout_with_marker(...).await {
Ok(applied) => Ok(applied),
Err(e) if e.to_string().contains("marker already set") => Ok(false),
Err(e) => Err(anyhow!("timeout failed: {e}")),
} Defensive patterns
Strategy: retry
Validate before calling
anyhow::ensure!(ctx.target_pubkey.is_some(), "timeout needs target"); anyhow::ensure!(ctx.timeout_until.is_some(), "timeout needs expiry"); anyhow::ensure!(ctx.timeout_until.unwrap() > chrono::Utc::now(), "expiry must be future");
Try / catch
for attempt in 0..3 {
match run_atomic_mutation(&state, ctx).await {
Ok(applied) => break Ok(applied),
Err(e) if e.to_string().contains("timeout failed") && attempt < 2 && is_transient(&e) => {
tokio::time::sleep(backoff(attempt)).await; // idempotent via action marker
}
Err(e) => break Err(e),
}
} Prevention
- Retry only transient DB errors; the marker makes the timeout idempotent per action_id.
- Log the complete error chain to expose the underlying Postgres cause.
- Validate timestamp ranges fit the DB column type before writing.
- Monitor Postgres connectivity from the enforcement driver.
When it happens
Trigger: Calling `execute_timeout_with_marker` when the DB operation errors: lease/marker conflict from a concurrent driver, missing user/community rows, invalid timestamp comparison, constraint violation, or Postgres connectivity failure.
Common situations: Two drivers racing to apply the same timeout action; the timed-out user record removed before enforcement; clock/timestamp values out of range for the DB column; transient Postgres outages under load.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- ban failed: {e}
- ban requires target_pubkey
- timeout requires target_pubkey
- timeout requires timeout_until
- kick requires target_pubkey
AI-assisted analysis of block/buzz@eed74bde2f (2026-08-30).
Data as JSON: /api/errors/336eddf57e841766.
Report an issue: GitHub.