block/buzz · error · anyhow::Error

PubSub init failed

Error message

PubSub init failed: {e}

What it means

Unlike pool creation, PubSubManager::new actually dials Redis to set up pub/sub plumbing. It fails on live connection problems: server unreachable (connection refused / DNS failure / firewall), auth failure (requirepass with no password or wrong one), or a Redis version/protocol mismatch. The wrapped {e} carries the underlying redis error.

Solutions

  1. Health-check with the same URL: redis-cli -u "$REDIS_URL" ping (expect PONG).
  2. Start Redis (docker compose up -d redis) or fix the host/port in REDIS_URL.
  3. Embed credentials if needed: redis://:password@host:6379, and rediss:// for TLS.
  4. If the job races container startup, add a readiness wait on the Redis port before invoking buzz-admin.

Example fix

# before
REDIS_URL=redis://redis:6379  # container still starting -> PubSub init failed
# after
until redis-cli -u "$REDIS_URL" ping 2>/dev/null | grep -q PONG; do sleep 1; done
buzz-admin add-member --pubkey <hex> --role member
Defensive patterns

Strategy: retry

Validate before calling

# preflight: prove Redis is reachable with the exact URL before the CLI runs
redis-cli -u "$REDIS_URL" ping | grep -q PONG || { echo 'Redis not ready' >&2; exit 3; }

Try / catch

// wrap admin invocations with bounded retry only for connection-class failures
for attempt in 0..3 {
    match run(cmd).await {
        Ok(v) => return Ok(v),
        Err(e) if e.to_string().contains("PubSub init failed") && attempt < 2 => {
            backoff(attempt).await;  // Redis may still be starting; retry with delay
        }
        Err(e) => return Err(e),   // auth/config failures will not heal — surface immediately
    }
}

Prevention

When it happens

Trigger: REDIS_URL points at a Redis that is down or firewalled; Redis requires a password and the URL lacks :password@; TLS mismatch (redis:// against a TLS-only port); k8s service not ready when the admin job starts.

Common situations: Running buzz-admin add-member without starting the docker-compose redis; rotating Redis credentials without updating REDIS_URL; job races a starting container.

Related errors


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

Appendix: source

Thrown at crates/buzz-admin/src/main.rs:572

                 The relay must have a stable signing key to publish kind:13534 events."
            )
        })?;
        Keys::parse(&hex).map_err(|e| anyhow::anyhow!("invalid BUZZ_RELAY_PRIVATE_KEY: {e}"))?
    };

    let redis_url =
        std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://localhost:6379".to_string());

    let redis_pool = {
        let cfg = deadpool_redis::Config::from_url(&redis_url);
        cfg.create_pool(Some(deadpool_redis::Runtime::Tokio1))
            .map_err(|e| anyhow::anyhow!("Redis pool creation failed: {e}"))?
    };

    let pubsub = Arc::new(
        PubSubManager::new(&redis_url, redis_pool)
            .await
            .map_err(|e| anyhow::anyhow!("PubSub init failed: {e}"))?,
    );

    Ok((db, pubsub, relay_keypair))
}

async fn connect_db() -> Result<Db> {
    let db_url = std::env::var("DATABASE_URL")
        .unwrap_or_else(|_| "postgres://buzz:buzz_dev@localhost:5432/buzz".to_string());
    let db = Db::new(
        &DbConfig {
            database_url: db_url,
            ..DbConfig::default()
        }
        .with_session_timeouts_from_env(),
    )
    .await?;
    Ok(db)
}

View on GitHub (pinned to ef2aa1ae38)