block/buzz · critical · anyhow::Error
Audit DB connection failed
Error message
Audit DB connection failed: {e} What it means
Fatal startup error: BUZZ_AUDIT_ENABLED=true, and the small dedicated audit pool (max 5 connections) failed to connect to config.database_url. The audit service keeps a hash-chain audit log in Postgres; without it the relay refuses to start because the operator has explicitly required auditing.
Solutions
- Verify connectivity again with the same URL: psql "$DATABASE_URL" -c 'select 1'
- Check Postgres max_connections headroom — the audit pool adds up to 5 more eager connections
- Restart once Postgres is stable
- If auditing is not actually required in this environment, set BUZZ_AUDIT_ENABLED=false (then audit is skipped at boot)
Defensive patterns
Strategy: retry
Validate before calling
# Reserve headroom: keep (relay pools + audit 5 + search 1) below Postgres # max_connections; check current usage before deploy: psql "$DATABASE_URL" -c 'show max_connections; select count(*) from pg_stat_activity;'
Try / catch
// Retry startup with backoff — the eager audit connect only fails when // Postgres is momentarily unavailable or connections are exhausted.
Prevention
- Account for the audit pool's 5 eager connections in DB sizing
- If audit is optional in a tier, leave BUZZ_AUDIT_ENABLED=false there
When it happens
Trigger: Postgres became unreachable between the main Db::new() connect and this one (e.g. failover, connection limit hit), or the URL allows the main pool's lazy dials but not additional eager connections (max_connections exhausted).
Common situations: Postgres connection budget consumed by other services so the extra eager pool connect fails; Postgres restarting mid-boot; audit enabled in an environment whose DB user has a hard connection cap.
Related errors
- DB connection failed
- Search DB connection failed
- Community deletion serving fence is unsafe
- Database migration failed
- Failed to backfill pubkey_allowlist (required when…
AI-assisted analysis of block/buzz@ef2aa1ae38 (2026-09-20).
Data as JSON: /api/errors/371346879db0e5d8.
Report an issue: GitHub.
Appendix: source
Thrown at crates/buzz-relay/src/main.rs:443
"Failed to bootstrap relay owner (non-fatal, membership not required): {e}"
);
}
}
}
}
// NIP-33: backfill d_tag for any existing parameterized replaceable events
// that predate the column addition. Idempotent — no-ops when fully populated.
match db.backfill_d_tags().await {
Ok(0) => {}
Ok(n) => info!("Backfilled d_tag for {n} NIP-33 events"),
Err(e) => error!("Failed to backfill d_tags: {e}"),
}
let (audit, audit_metrics_pool) = if config.audit_enabled {
let audit_pool = connect_audit_pool(&db_config)
.await
.map_err(|e| anyhow::anyhow!("Audit DB connection failed: {e}"))?;
info!("Audit service ready");
let metrics_pool = audit_pool.clone();
(Some(AuditService::new(audit_pool)), Some(metrics_pool))
} else {
info!("Audit logging disabled by BUZZ_AUDIT_ENABLED");
(None, None)
};
let redis_pool = {
let mut cfg = deadpool_redis::Config::from_url(&config.redis_url);
cfg.pool = Some(deadpool_redis::PoolConfig::new(config.redis_pool_size));
cfg.create_pool(Some(deadpool_redis::Runtime::Tokio1))
.map_err(|e| anyhow::anyhow!("Redis pool creation failed: {e}"))?
};
let redis_health_pool = redis_pool.clone(); // cheap Arc clone — shared with readiness handler
let pubsub = Arc::new(
PubSubManager::new(&config.redis_url, redis_pool)
.awaitView on GitHub (pinned to ef2aa1ae38)