block/buzz · warning · anyhow::Error
deletion request is not runnable, is blocked, or is leased b
Error message
deletion request is not runnable, is blocked, or is leased by another executor
What it means
In LoopMode::Run (the single-shot 'run' invocation), the executor asked the store for a claim — claim_specific(id) when --id was passed, otherwise claim_next(executor_id) — and got None back. None means the store found no claimable request: the target request is not in a runnable stage, is blocked (blocked_reason set), or its lease is held by another executor and not yet expired. Because 'run' implies the operator expected work to happen, the absence of any claim (and nothing having run yet, !ran) is surfaced as an error instead of a silent zero exit. In loop mode the same condition just returns 0 — a quiet poll.
Source
Thrown at crates/buzz-deletion/src/lib.rs:824
return Ok(0);
}
let claim = match request_id {
Some(id) => {
services
.store
.claim_specific(id, &executor_id, DEFAULT_LEASE_DURATION)
.await?
}
None => {
services
.store
.claim_next(&executor_id, DEFAULT_LEASE_DURATION)
.await?
}
};
let Some(claim) = claim else {
if mode == LoopMode::Run && !ran {
anyhow::bail!(
"deletion request is not runnable, is blocked, or is leased by another executor"
);
}
return Ok(0);
};
ran = true;
let output = execute_claim(&services, mode, claim, &shutdown).await?;
print_json(&output)?;
let failed = output.last_error.is_some() || output.blocked_reason.is_some();
if mode == LoopMode::Run || shutdown.is_cancelled() || failed {
return Ok(i32::from(failed));
}
}
}
async fn stop_claim_executor(
services: &Services,
mode: LoopMode,View on GitHub (pinned to f956e6fe06)
Solutions
- Check the request's state first (store listing/admin output): if it is Submitted or Inventoried, advance it through the explicit approval boundary before running.
- If a blocked_reason is recorded, resolve that blocker (or abort) — blocked requests are never claimable.
- If another executor (loop daemon) is live, let it own the request or stop it, then wait out the lease duration before re-running so the expired lease can be reclaimed.
- Pass --id only for a request you have confirmed is approved and unleased; a bare run is the right form for 'pick up whatever is ready'.
Example fix
# before: run issued before approval buzz-deletion submit --host localhost:3000 --requester npub1... --reason gdpr buzz-deletion run --id <request-id> # error: deletion request is not runnable, is blocked, or is leased by another executor # after: approve first, then run buzz-deletion approve --id <request-id> buzz-deletion run --id <request-id>
Defensive patterns
Strategy: retry
Validate before calling
# preflight: confirm the request is approved and unleased before one-shot run psql "$DATABASE_URL" -c "SELECT id, stage, blocked_reason, lease_expires_at FROM deletion_requests WHERE id = '<uuid>';" # runnable only if stage is approved-or-later, blocked_reason IS NULL, and no live lease
Try / catch
# safe to retry after backoff >= lease duration: claim is atomic and idempotent
rc=1
for i in 1 2 3; do buzz-deletion run --id "$RID" && { rc=0; break; }; sleep 60; done; exit $rc Prevention
- Automate submit → approve → run as distinct gated steps; never chain submit directly into run.
- Run exactly one executor (loop daemon OR one-shot CLI) per database to avoid lease races.
- After a crashed executor, wait out DEFAULT_LEASE_DURATION before re-running so the lease can be reclaimed.
When it happens
Trigger: `buzz-deletion run --id <uuid>` when that request is still awaiting approval (Submitted/Inventoried), blocked by a dependency, or another executor/loop holds its lease; bare `buzz-deletion run` when every queued request is blocked or leased elsewhere (e.g. the loop daemon is already running against the same DB).
Common situations: Operator submits then immediately runs without the approval step; running the one-shot CLI while the long-lived loop executor is mid-deletion; retrying run for a request that previously failed into a blocked state; lease not yet expired after a crashed executor (DEFAULT_LEASE_DURATION must elapse before reclaim).
Related errors
- request has not crossed the explicit approval boundary
- --host must not be empty
- cannot derive community host; pass --host or set RELAY_URL
- cannot derive community host from RELAY_URL; pass --host or
- {name} is required for community deletion
AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16).
Data as JSON: /api/errors/7eceae3d3636c47d.
Report an issue: GitHub.