redis/go-redis · critical

redis: failed to create pipeline connection pool: %w

Error message

redis: failed to create pipeline connection pool: %w

What it means

Panics when building the dedicated pipeline connection pool fails. This pool is optional: it is only created when PipelinePoolSize >= 0, and its construction failure means invalid pool options. The panic aborts NewClient since pipeline behavior would be inconsistent.

Source

Thrown at redis.go:2132

	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)
		c.connPool.AddPoolHook(c.streamingCredentialsManager.PoolHook())
		if pp := c.getPipelinePool(); pp != nil {
			pp.AddPoolHook(c.streamingCredentialsManager.PoolHook())
		}
	}

	// CSC wiring (SharedTracking): shared cache + per-connection CLIENT TRACKING +
	// background drainer. attachCSC is the strategy dispatch entry.
	if opt.Protocol == 3 {
		var cache Cache
		if explicit := opt.ClientSideCache; explicit != nil {
			cache = explicit

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Read the wrapped cause (%w) to find the invalid option
  2. If pipelines are not needed, set Options.PipelinePoolSize = -1 to opt out of the pool entirely
  3. Fix the conflicting redis.Options field

Example fix

// before
opt := &redis.Options{Addr: addr, PipelinePoolSize: 16, ReadBufferSize: -32}
// after
opt := &redis.Options{Addr: addr, PipelinePoolSize: 16} // valid buffers/default
Defensive patterns

Strategy: validation

Validate before calling

if opt.PipelinePoolSize > 0 && opt.PoolSize <= 0 { return errors.New("PipelinePoolSize requires a valid PoolSize") }
client := redis.NewClient(opt)

Try / catch

defer func() {
    if r := recover(); r != nil {
        err = fmt.Errorf("redis client init failed: %v", r)
    }
}()

Prevention

When it happens

Trigger: Calling redis.NewClient with Options.PipelinePoolSize >= 0 (opt-in) while other pool options cause buildPipelinePool to fail, at redis.go:2132.

Common situations: Setting PipelinePoolSize explicitly for the first time and combining it with an invalid main-pool/buffer option; validating config only partially.

Related errors


AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01). Data as JSON: /api/errors/a48f1738a17b607a. Report an issue: GitHub.