{"record":{"id":"85b690070ed09065","repo":"block/buzz","slug":"ban-failed-e","errorCode":null,"errorMessage":"ban failed: {e}","messagePattern":"ban failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/buzz-relay/src/handlers/report_resolution.rs","lineNumber":699,"sourceCode":"    // ownership fence rejected the transaction (lease lost or marker already set\n    // by a concurrent driver). We classify Ok(false) by reloading the row.\n    let raw: anyhow::Result<bool> = match ctx.action {\n        \"ban\" => {\n            let target = ctx\n                .target_pubkey\n                .ok_or_else(|| anyhow::anyhow!(\"ban requires target_pubkey\"))?;\n            state\n                .db\n                .execute_ban_with_marker(\n                    action_id,\n                    lease_token,\n                    ctx.community_id,\n                    target,\n                    ctx.actor_pubkey,\n                    ctx.reason,\n                )\n                .await\n                .map_err(|e| anyhow::anyhow!(\"ban failed: {e}\"))\n        }\n        \"timeout\" => {\n            let target = ctx\n                .target_pubkey\n                .ok_or_else(|| anyhow::anyhow!(\"timeout requires target_pubkey\"))?;\n            let until = ctx\n                .timeout_until\n                .ok_or_else(|| anyhow::anyhow!(\"timeout requires timeout_until\"))?;\n            state\n                .db\n                .execute_timeout_with_marker(\n                    action_id,\n                    lease_token,\n                    ctx.community_id,\n                    target,\n                    ctx.actor_pubkey,\n                    until,\n                    ctx.reason,","sourceCodeStart":681,"sourceCodeEnd":717,"githubUrl":"https://github.com/block/buzz/blob/eed74bde2f4797714335ac10c56c0b0244c1def4/crates/buzz-relay/src/handlers/report_resolution.rs#L681-L717","documentation":"The 'ban' arm of `run_atomic_mutation` wraps any failure from `state.db.execute_ban_with_marker` with 'ban failed: {e}'. The context (target was present, lease held) was valid, but the database-level ban operation itself returned an error, which is re-wrapped for the enforcement driver to record.","triggerScenarios":"Calling `execute_ban_with_marker` for an action where the DB operation fails: lease/marker ownership conflict, community or user row missing, foreign-key violation, deadlock, or Postgres connectivity failure during the atomic mutation.","commonSituations":"Two enforcement drivers racing on the same action (marker already set); target user or community id no longer exists in the DB; transient Postgres connection drops under load; schema migration drift between the relay and the database.","solutions":["Read the inner `{e}` message in the error chain to identify the DB-level cause (constraint, lease conflict, connectivity).","If it is a lease/marker conflict, the action was already processed — treat Ok(false)/duplicate as expected and skip.","Check Postgres health and migrations (`just test` integration suite reproduces DB-dependent failures locally).","Retry the enforcement driver after transient DB errors; the atomic marker design makes ban idempotent per action_id."],"exampleFix":"// before\nexecute_ban_with_marker(...).await.map_err(|e| anyhow!(\"ban failed: {e}\"))\n// after — tolerate already-applied marker\nmatch execute_ban_with_marker(...).await {\n  Ok(applied) => Ok(applied),\n  Err(e) if e.to_string().contains(\"marker already set\") => Ok(false),\n  Err(e) => Err(anyhow!(\"ban failed: {e}\")),\n}","handlingStrategy":"retry","validationCode":"anyhow::ensure!(ctx.target_pubkey.is_some(), \"refusing to enqueue ban without target\");\nanyhow::ensure!(state.db.ping().await.is_ok(), \"postgres unreachable before ban\");","typeGuard":null,"tryCatchPattern":"for attempt in 0..3 {\n  match run_atomic_mutation(&state, ctx).await {\n    Ok(applied) => break Ok(applied),\n    Err(e) if e.to_string().contains(\"ban failed\") && attempt < 2 && is_transient(&e) => {\n      tokio::time::sleep(backoff(attempt)).await; // marker design makes retry safe\n    }\n    Err(e) => break Err(e),\n  }\n}","preventionTips":["Back ban writes with the idempotent action marker and retry only transient DB errors.","Monitor Postgres health; alert on constraint/deadlock errors from the enforcement driver.","Keep relay and DB schema migrations in lockstep.","Log the full anyhow error chain so the inner DB cause is visible."],"tags":["moderation","database","postgres","rust","backend"],"backgroundTag":"database-operation-failed","analyzedSha":"eed74bde2f4797714335ac10c56c0b0244c1def4","analyzedAt":"2026-08-30T13:49:18.474Z","contentChangedAt":"2026-08-30T13:49:18.474Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}