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

  1. 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.
  2. If a blocked_reason is recorded, resolve that blocker (or abort) — blocked requests are never claimable.
  3. 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.
  4. 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

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


AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16). Data as JSON: /api/errors/7eceae3d3636c47d. Report an issue: GitHub.