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-owned

View on GitHub (pinned to f956e6fe06)

Solutions

  1. From the relay's container/host, verify Redis end-to-end: redis-cli -u "$REDIS_URL" ping.
  2. Fix REDIS_URL (host, port, auth, rediss:// for TLS) and confirm the ACL user can SET keys.
  3. If the mesh was not intended, unset BUZZ_MESH — the relay reverts to exact single-instance behavior with no Redis writes.
  4. 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

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


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