block/buzz · error
mesh ready-registry publish failed: {e}
Error message
mesh ready-registry publish failed: {e} What it means
After the mesh endpoint binds, boot_mesh builds a signed ReadyRecord (attested with the relay keypair) and publishes it to Redis: ReadyRegistry::publish_ready (registry.rs:182) self-verifies the attestation, JSON-encodes the record, and runs SET <ready-key> <payload> EX <ttl> over a deadpool-redis connection. The first publish is deliberately part of boot — the comment in mesh_boot.rs says if Redis cannot take the attested record, peers can never find this relay, so startup fails loudly instead of running silently undiscoverable. Errors surface as MeshError (connection/pool/Redis failures or attestation verification).
Source
Thrown at crates/buzz-relay/src/mesh_boot.rs:462
// foreign and rejected (Wren's review — possession is not authorization).
let membership = MeshMembership::new(local_record)
.with_expected_relay_pubkey(relay_keypair.public_key().to_hex());
let registry = ReadyRegistry::new(redis_pool.clone(), config.mesh.registry_refresh);
let ready_record = ReadyRecord::new(
runtime_id,
relay_keypair,
addrs,
PROTO_VERSION,
capabilities(),
);
// First publish is part of boot: if Redis can't take the attested record,
// peers can never find us — fail loudly now, not quietly forever.
registry
.publish_ready(&ready_record)
.await
.map_err(|e| anyhow::anyhow!("mesh ready-registry publish failed: {e}"))?;
tracing::info!(runtime_id = %runtime_id, "mesh ready record published");
// Readiness-gated heartbeat: publishes while the relay would pass
// readiness, clears the record on ready→not-ready and on shutdown.
let hb_flag = Arc::clone(&shutting_down);
buzz_relay_mesh::runtime::spawn_registry_heartbeat(
registry.clone(),
ready_record,
Arc::new(move || !hb_flag.load(Ordering::Relaxed)),
);
let runtime = MeshRuntime::start(endpoint, membership, Some(registry));
let owners = Arc::new(crate::audio::join::HuddleOwnerRegistry::new());
// Dial seed peers now rather than waiting for the first reconcile tick.
runtime.reconcile_now().await;
// Drain watcher: SIGTERM flips `shutting_down`; gossip `draining=true` so
// peers stop routing new sessions here, then actively drain locally-ownedView on GitHub (pinned to f956e6fe06)
Solutions
- From the relay's container/host, verify Redis end-to-end: redis-cli -u "$REDIS_URL" ping.
- Fix REDIS_URL (host, port, auth, rediss:// for TLS) and confirm the ACL user can SET keys.
- If the mesh was not intended, unset BUZZ_MESH — the relay reverts to exact single-instance behavior with no Redis writes.
- After Redis is healthy, restart the relay: there is no boot-time retry by design; the readiness-gated heartbeat only maintains the record after the first publish succeeds.
Example fix
# before: BUZZ_MESH=on, REDIS_URL=redis://localhost:6379 (Redis not running) # Error: mesh ready-registry publish failed: ... # after REDIS_URL=redis://redis.internal:6379 # reachable, then restart the relay
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: prove Redis is reachable before enabling the mesh.
async fn redis_reachable(url: &str) -> bool {
let Ok(client) = redis::Client::open(url) else { return false };
let Ok(mut conn) = client.get_connection_manager().await else { return false };
redis::cmd("PING").query_async::<String>(&mut conn).await.is_ok()
}
let url = std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://localhost:6379".into());
assert!(redis_reachable(&url).await, "REDIS_URL {url} not reachable — fix it before BUZZ_MESH=on"); Type guard
fn is_redis_conn_err(e: &anyhow::Error) -> bool {
let msg = e.to_string().to_lowercase();
msg.contains("redis") || msg.contains("connection refused") || msg.contains("pool")
} Try / catch
if let Err(e) = registry.publish_ready(&ready_record).await {
tracing::error!(
%e,
redis_url = std::env::var("REDIS_URL").unwrap_or_default(),
"first ready publish failed — peers cannot discover this relay"
);
return Err(anyhow!("mesh ready-registry publish failed: {e}"));
} Prevention
- PING Redis from the relay container's entrypoint before starting with BUZZ_MESH=on
- Keep REDIS_URL and BUZZ_MESH in the same env template so they are changed together
- Order compose/k8s dependencies so Redis is healthy before the relay starts (health-check gates)
When it happens
Trigger: BUZZ_MESH=on with REDIS_URL (default redis://localhost:6379, config.rs:515) pointing at a Redis that is down, firewalled, ACL/auth-mismatched, or a deadpool that cannot hand out a connection; TLS scheme mismatch (rediss:// vs redis://); attestation self-verification failing (practically a bug, since the record is generated and signed in the same boot path).
Common situations: Enabling the mesh before Redis is reachable; k8s NetworkPolicy blocking relay-to-Redis traffic; Redis restarted with requirepass/ACL changes; compose files where redis starts later than the relay and there is no health-check dependency.
Related errors
- mesh endpoint bind on {} failed: {e}
- Redis pool creation failed: {e}
- PubSub init failed: {e}
- git conformance probe failed: {e}
- Failed to bind health port {}: {e}
AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16).
Data as JSON: /api/errors/86349a1b6a92db26.
Report an issue: GitHub.