redis/go-redis · critical
redis: failed to create pubsub pool: %w
Error message
redis: failed to create pubsub pool: %w
What it means
Raised when constructing the dedicated PubSub connection pool during client creation fails. Like the main pool, failure means an invalid pool configuration rather than a network problem. NewClient panics because the client would be unusable without its pubsub pool.
Source
Thrown at redis.go:2120
// Use void processor for RESP2 connections (push notifications not available)
c.pushProcessor = initializePushProcessor(opt)
// set opt push processor for child clients
c.opt.PushNotificationProcessor = c.pushProcessor
// Generate unique pool names for metrics
uniqueID := generateUniqueID()
mainPoolName := opt.Addr + "_" + uniqueID
pubsubPoolName := opt.Addr + "_" + uniqueID + "_pubsub"
// Create connection pools
var err error
c.connPool, err = newConnPool(opt, c.dialHook, mainPoolName)
if err != nil {
panic(fmt.Errorf("redis: failed to create connection pool: %w", err))
}
c.pubSubPool, err = newPubSubPool(opt, c.dialHook, pubsubPoolName)
if err != nil {
panic(fmt.Errorf("redis: failed to create pubsub pool: %w", err))
}
// Create the dedicated pipeline pool unconditionally, like pubSubPool: it
// is pure burst capacity (no pre-dialing, small cap, larger buffers — see
// pipelinePoolOptions), so an unused pipeline pool holds zero connections
// and costs nothing. Pipelines stop competing with regular commands for
// main-pool connections; a burst wider than the pool's cap spills back to
// the main pool (see withPipelineConn). PipelinePoolSize < 0 opts out.
if opt.PipelinePoolSize >= 0 {
ref, err := c.buildPipelinePool(opt.Addr + "_" + uniqueID + "_pipeline")
if err != nil {
panic(fmt.Errorf("redis: failed to create pipeline connection pool: %w", err))
}
c.pipelinePool = ref
}
if opt.StreamingCredentialsProvider != nil {
c.streamingCredentialsManager = streaming.NewManager(c.connPool, c.opt.PoolTimeout)View on GitHub (pinned to c5cad058c7)
Solutions
- Inspect the wrapped inner error to identify the bad option
- Correct the invalid redis.Options field used for the pubsub pool
- If pubsub is unused, still fix Options — the pool is created unconditionally
Example fix
// before
redis.NewClient(&redis.Options{Addr: addr, ReadBufferSize: -1})
// after
redis.NewClient(&redis.Options{Addr: addr}) // let the library use defaults Defensive patterns
Strategy: validation
Validate before calling
if opt.ReadBufferSize < 0 || opt.WriteBufferSize < 0 { return errors.New("buffer sizes must be non-negative") }
client := redis.NewClient(opt) Try / catch
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("redis client init failed: %v", r)
}
}() Prevention
- Do not set buffer/pool fields unless you have a specific reason
- Validate Options struct with a helper before constructing any client
- Log the full Options (minus credentials) when initialization panics
When it happens
Trigger: redis.NewClient with Options that make newPubSubPool fail (invalid pool sizing/buffer options affecting the pubsub pool), at redis.go:2120.
Common situations: The same invalid Options that break the main pool usually hit here right after error 200 — e.g. invalid ReadBufferSize/WriteBufferSize or negative size fields; building Options from unvalidated config files.
Related errors
- redis: failed to create connection pool: %w
- redis: failed to create pipeline connection pool: %w
- redis: failed to create pubsub pool: %w
- failed to create operation duration histogram: %w
- failed to create connection count metric: %w
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/e51461df34c9d844.
Report an issue: GitHub.