block/buzz · critical · anyhow::Error

PubSub init failed: {e}

Error message

PubSub init failed: {e}

What it means

PubSubManager::new() establishes the Redis connection used for pub/sub fan-out (multi-node event distribution, presence, typing indicators). Unlike pool creation, this actually dials Redis, so an unreachable server, auth failure, or ACL restriction aborts startup with the underlying error.

Source

Thrown at crates/buzz-relay/src/main.rs:379

            .map_err(|e| anyhow::anyhow!("Audit DB connection failed: {e}"))?;
        info!("Audit service ready");
        Some(AuditService::new(audit_pool))
    } else {
        info!("Audit logging disabled by BUZZ_AUDIT_ENABLED");
        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)
            .await
            .map_err(|e| anyhow::anyhow!("PubSub init failed: {e}"))?,
    );
    info!("Redis pub/sub connected");

    // Spawn Redis pub/sub subscriber for multi-node fan-out.
    // Events published by other relay instances are received here and
    // fanned out to local WebSocket subscribers.
    let pubsub_for_sub = Arc::clone(&pubsub);
    tokio::spawn(async move { pubsub_for_sub.run_subscriber().await });

    // Spawn Redis pub/sub subscriber for cross-pod cache-key invalidation.
    // Membership / visibility changes on other pods are received here and the
    // matching local moka caches are dropped (via the consumer loop below).
    let pubsub_for_cache = Arc::clone(&pubsub);
    tokio::spawn(async move { pubsub_for_cache.run_cache_invalidation_subscriber().await });

    // Spawn Redis pub/sub subscriber for cross-pod connection-control commands.
    // Bans recorded on other pods are received here and applied to any local
    // sockets (via the consumer loop below), enforcing live disconnect fan-out.

View on GitHub (pinned to f956e6fe06)

Solutions

  1. Verify reachability and auth: `redis-cli -u "$REDIS_URL" ping`
  2. Start Redis / fix host+port / add credentials to REDIS_URL
  3. For managed Redis use rediss:// and confirm the ACL allows pub/sub commands
Defensive patterns

Strategy: retry

Validate before calling

# Pub/sub actually dials Redis — prove reachability and auth first.
redis-cli -u "$REDIS_URL" ping || { echo 'redis unreachable or auth failed'; exit 1; }

Try / catch

relay:
  restart: on-failure:5
redis:
  healthcheck:
    test: ["CMD", "redis-cli", "ping"]

Prevention

When it happens

Trigger: Redis not running or wrong host/port; AUTH required but no credentials in REDIS_URL; the Redis user's ACL lacks SUBSCRIBE/PUBLISH; TLS mismatch against managed Redis.

Common situations: Redis container starting later than the relay; ElastiCache/managed Redis requiring rediss:// or AUTH; VPC/security groups blocking 6379; connection limits exhausted.

Related errors


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