block/buzz · critical · anyhow::Error
Community deletion serving fence is unsafe: {e}
Error message
Community deletion serving fence is unsafe: {e} What it means
Fatal startup error from db.validate_deletion_serving_catalog(), which verifies the catalog backing the community-deletion serving fence — the mechanism that keeps a half-deleted community from serving stale events. If catalog shape or contents cannot be proven safe, the relay refuses to boot rather than serve potentially unfenced data. The source notes migration 0021 as the floor-guard schema this depends on.
Source
Thrown at crates/buzz-relay/src/main.rs:206
let auto_migrate =
buzz_auto_migrate_enabled(std::env::var("BUZZ_AUTO_MIGRATE").ok().as_deref());
if auto_migrate {
db.migrate().await.map_err(|e| {
error!("Failed to run database migrations: {e}");
anyhow::anyhow!("Database migration failed: {e}")
})?;
info!("Database migrations complete");
} else {
info!("Skipping database migrations because BUZZ_AUTO_MIGRATE is not enabled");
}
if let Err(e) = db.ensure_future_partitions(3).await {
error!("Failed to ensure partitions: {e}");
}
db.validate_deletion_serving_catalog().await.map_err(|e| {
error!("Community deletion serving-fence validation failed: {e}");
anyhow::anyhow!("Community deletion serving fence is unsafe: {e}")
})?;
info!("Community deletion serving fences verified");
// Freshness fence probe: cursor pages route to the replica only for
// history the probe has verified as fully replayed. Deliberately AFTER
// the migration decision: spawn_fence_probe first verifies the
// commit-time floor guard (catalog shape + observed behavior through the
// armed pool) against the live schema, so a relay running with
// BUZZ_AUTO_MIGRATE off and migration 0021 unapplied can never open the
// fence over an unenforced floor. Verification failure is loud but
// non-fatal: the fence stays closed and every cursor page routes to the
// writer.
match db.spawn_fence_probe().await {
Ok(true) => info!("Replica fence probe started (floor guard verified)"),
Ok(false) => {}
Err(e) => {
error!(
"Replica fence disabled — floor guard verification failed: {e}. \View on GitHub (pinned to f956e6fe06)
Solutions
- Apply pending migrations (enable BUZZ_AUTO_MIGRATE once, or run them manually), then restart
- Inspect {e} for the specific catalog/table mismatch it names
- Compare the live schema against migrations/ up to HEAD, focusing on the deletion-serving fence migration
- If the catalog was hand-edited, restore from a known-good backup rather than patching rows
Defensive patterns
Strategy: validation
Validate before calling
# Fence depends on current schema: assert applied migrations match migrations/ HEAD.
latest=$(ls migrations | grep -oE '^[0-9]+' | sort -n | tail -1)
applied=$(psql "$DATABASE_URL" -tAc "select max(version) from _sqlx_migrations")
[ "$latest" = "$(echo $applied | tr -d ' ')" ] || { echo 'fence catalog may be stale: apply migrations'; exit 1; } Prevention
- Never hand-edit fence/catalog tables; change them only through migrations
- Keep BUZZ_AUTO_MIGRATE on, or make external migration application a deploy gate
- After restoring from backup, re-run the fence validation before returning the relay to service
When it happens
Trigger: Running with BUZZ_AUTO_MIGRATE off while fence-related migrations (0021 era) are unapplied; fence catalog tables missing or malformed; manually edited catalog rows.
Common situations: New binary against a database whose migrations are pinned/managed externally and one was skipped; partial database restore; environments where DBAs cherry-pick migrations.
Related errors
- Database migration failed: {e}
- DB connection failed: {e}
- Failed to ensure deployment community (required when BUZZ_RE
- Failed to backfill pubkey_allowlist (required when BUZZ_REQU
- Failed to bootstrap relay owner (required when BUZZ_REQUIRE_
AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16).
Data as JSON: /api/errors/a937a169e15458e6.
Report an issue: GitHub.