{"record":{"id":"86349a1b6a92db26","repo":"block/buzz","slug":"mesh-ready-registry-publish-failed-e","errorCode":null,"errorMessage":"mesh ready-registry publish failed: {e}","messagePattern":"mesh ready-registry publish failed: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/buzz-relay/src/mesh_boot.rs","lineNumber":462,"sourceCode":"    // foreign and rejected (Wren's review — possession is not authorization).\n    let membership = MeshMembership::new(local_record)\n        .with_expected_relay_pubkey(relay_keypair.public_key().to_hex());\n\n    let registry = ReadyRegistry::new(redis_pool.clone(), config.mesh.registry_refresh);\n    let ready_record = ReadyRecord::new(\n        runtime_id,\n        relay_keypair,\n        addrs,\n        PROTO_VERSION,\n        capabilities(),\n    );\n\n    // First publish is part of boot: if Redis can't take the attested record,\n    // peers can never find us — fail loudly now, not quietly forever.\n    registry\n        .publish_ready(&ready_record)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"mesh ready-registry publish failed: {e}\"))?;\n    tracing::info!(runtime_id = %runtime_id, \"mesh ready record published\");\n\n    // Readiness-gated heartbeat: publishes while the relay would pass\n    // readiness, clears the record on ready→not-ready and on shutdown.\n    let hb_flag = Arc::clone(&shutting_down);\n    buzz_relay_mesh::runtime::spawn_registry_heartbeat(\n        registry.clone(),\n        ready_record,\n        Arc::new(move || !hb_flag.load(Ordering::Relaxed)),\n    );\n\n    let runtime = MeshRuntime::start(endpoint, membership, Some(registry));\n    let owners = Arc::new(crate::audio::join::HuddleOwnerRegistry::new());\n    // Dial seed peers now rather than waiting for the first reconcile tick.\n    runtime.reconcile_now().await;\n\n    // Drain watcher: SIGTERM flips `shutting_down`; gossip `draining=true` so\n    // peers stop routing new sessions here, then actively drain locally-owned","sourceCodeStart":444,"sourceCodeEnd":480,"githubUrl":"https://github.com/block/buzz/blob/934f3325c3fdaa3a6f23134b74518139aac8ca3f/crates/buzz-relay/src/mesh_boot.rs#L444-L480","documentation":"mesh_boot publishes the relay's attested ready-record to the Redis ready-registry as part of boot; the source comment is explicit — if Redis cannot take the record, peers can never discover this instance, so boot fails loudly instead of running undiscoverable. Any error from registry.publish_ready (Redis connection, TLS, auth, serialization of the attested record) is wrapped as 'mesh ready-registry publish failed' and aborts relay startup when mesh is enabled.","triggerScenarios":"registry.publish_ready(&ready_record) at crates/buzz-relay/src/mesh_boot.rs:458-462 fails when: Redis is unreachable (wrong host/port in the mesh registry config), rediss:// TLS cert validation fails (ElastiCache), auth credentials are wrong (NOAUTH/WRONGPASS), the key is under a write-protected policy, or the record exceeds Redis protocol limits.","commonSituations":"Enabling BUZZ_MESH=on locally without the staging Redis running or reachable; ElastiCache in-transit encryption enabled but the relay's Redis URL uses redis:// instead of rediss://; rotated Redis credentials not deployed to the K8s secret; security-group rules blocking the node's egress to Redis port 6379.","solutions":["Verify Redis reachability from the relay host: `redis-cli -u <url> PING` (use rediss:// and --tls for TLS endpoints).","Fix the URL scheme: rediss:// for TLS-encrypted Redis (ElastiCache), redis:// only for plaintext.","Check credentials/ACLs: the relay's Redis user needs SET/PUBLISH on the ready-registry keys.","Open network egress (security groups / NetworkPolicies) to the Redis port.","If you only want single-instance behavior, set BUZZ_MESH to a value other than 'on' — mesh_boot then skips registry publish entirely."],"exampleFix":"# before\nBUZZ_MESH=on\nBUZZ_REDIS_URL=redis://mesh-redis.internal:6379  # against TLS-enabled ElastiCache\n\n# after\nBUZZ_MESH=on\nBUZZ_REDIS_URL=rediss://mesh-redis.internal:6379","handlingStrategy":"retry","validationCode":"# preflight from the relay host before enabling mesh\nredis-cli --tls -u \"$BUZZ_REDIS_URL\" PING   # expect PONG","typeGuard":null,"tryCatchPattern":"// at boot: retry the publish briefly before failing fast, so a restarting Redis\n// does not take the relay down\nlet mut attempt = 0;\nloop {\n    match registry.publish_ready(&ready_record).await {\n        Ok(()) => break,\n        Err(e) if attempt < 5 => { attempt += 1; tokio::time::sleep(Duration::from_secs(2)).await; }\n        Err(e) => return Err(anyhow::anyhow!(\"mesh ready-registry publish failed: {e}\")),\n    }\n}","preventionTips":["Start/verify Redis before relays in compose/ArgoCD ordering (init containers or readiness gates).","Standardize rediss:// + TLS for ElastiCache in all environments to avoid scheme drift.","Keep mesh registry credentials in the same secret rotation flow as the main cache to avoid partial rotations.","Remember the fail-fast is intentional — do not silence it; fix reachability instead."],"tags":["rust","redis","mesh","startup","service-discovery","tls"],"backgroundTag":"redis-connection-failed","analyzedSha":"934f3325c3fdaa3a6f23134b74518139aac8ca3f","analyzedAt":"2026-08-20T04:38:24.874Z","contentChangedAt":"2026-08-20T04:38:24.874Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}