block/buzz · error

repo announcement rejected by community deletion fence: {e}

Error message

repo announcement rejected by community deletion fence: {e}

What it means

Before writing a repo announcement, the relay acquires a serving lease via buzz_deletion::acquire_serving_write. This coordinates with the community deletion fence so writes are rejected while a community deletion is in flight. This error wraps that acquisition failure — the community is (or may be) being deleted, so the announcement write is refused.

Source

Thrown at crates/buzz-relay/src/handlers/side_effects.rs:2677

    // pointer failure. An `AlreadyOwned` outcome means the row is owned by some
    // other attempt (a same-owner sibling, or a prior announce that has since
    // pushed), and deleting it here would strand a repo whose pointer that
    // other attempt already established.
    let reserved_by_this_attempt = matches!(outcome, ReserveOutcome::Reserved);

    // The event row and name registry are ordinary database state: if deletion
    // quiescing wins before they commit, the DB write fence rejects them; if
    // they committed first, the destructive DB stage purges them. The manifest
    // and pointer below are external S3 effects, so acquire the durable
    // serving-write lease immediately before that sequence. Once acquired,
    // deletion must drain this lease before it can freeze the final object list.
    let serving_write = buzz_deletion::acquire_serving_write(
        &state.db,
        tenant.community(),
        "git_repo_announcement",
    )
    .await
    .map_err(|e| anyhow::anyhow!("repo announcement rejected by community deletion fence: {e}"))?;

    #[cfg(test)]
    if let Some(gate) = &hooks.post_lease_gate {
        gate.reached.notify_one();
        gate.resume.notified().await;
    }

    if let Err(error) = serving_write.verify().await {
        return Err(anyhow::anyhow!(
            "repo announcement lost community serving lease: {error}"
        ));
    }

    // Establish/confirm the manifest pointer, keeping the invariant
    // "repo announced ⟺ pointer exists" so the read path can rely on
    // pointer-absent meaning never-announced (keeping `info_refs`'s fail-closed
    // `Ok(None) → 404` unambiguous). Two distinct cases:
    //

View on GitHub (pinned to dad5a33865)

Solutions

  1. Retry the announcement after the community deletion completes (or is confirmed cancelled).
  2. Check the deletion fence state for the community; if a deletion is stuck, reconcile/reset the fence via buzz_deletion tooling.
  3. Verify you are announcing into the intended community/tenant — a wrong community id may map to one being deleted.
  4. Inspect the wrapped {e} detail to distinguish 'actively deleting' from 'fence stuck' and act accordingly.
Defensive patterns

Strategy: retry

Validate before calling

// check fence state before attempting the write
let serving = buzz_deletion::serving_state(&state.db, community).await?;
anyhow::ensure!(serving.is_active(), "community {community} not actively serving");

Try / catch

match acquire_serving_write(&db, community, "git_repo_announcement").await {
    Err(e) if e.to_string().contains("deletion fence") => {
        tokio::time::sleep(Duration::from_secs(5)).await;
        // retry after deletion window settles, or surface to operator
    }
    r => r,
}

Prevention

When it happens

Trigger: Publishing a kind:30617 announcement concurrently with a community deletion operation for the same tenant; a stale or failed deletion run left the fence closed so normal writes cannot acquire the lease.

Common situations: An operator deleting a community while clients still announce repos into it; a crashed/interrupted deletion process that never released or reopened the fence; test environments where deletion fence state persists across runs.

Related errors


AI-assisted analysis of block/buzz@dad5a33865 (2026-08-30). Data as JSON: /api/errors/e61b18590260e8d4. Report an issue: GitHub.