{"id":"e00501dc1200912a","repo":"go-redis/redis","slug":"redis-failed-to-create-pipeline-connection-pool","errorCode":null,"errorMessage":"redis: failed to create pipeline connection pool: %w","messagePattern":"redis: failed to create pipeline connection pool: %w","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"redis.go","lineNumber":1987,"sourceCode":"\t\t\t// parsing needs a minimum read buffer, and a tiny pipeline reader\n\t\t\t// would break push-notification handling on pipeline conns.\n\t\t\tif pipelineOpt.Protocol == 3 && pipelineOpt.ReadBufferSize < proto.MinRESP3ReadBufferSize {\n\t\t\t\tpipelineOpt.ReadBufferSize = proto.MinRESP3ReadBufferSize\n\t\t\t}\n\t\t}\n\t\tif opt.PipelineWriteBufferSize > 0 {\n\t\t\tpipelineOpt.WriteBufferSize = opt.PipelineWriteBufferSize\n\t\t}\n\t\tif opt.PipelinePoolSize > 0 {\n\t\t\tpipelineOpt.PoolSize = opt.PipelinePoolSize\n\t\t} else {\n\t\t\tpipelineOpt.PoolSize = 10 // default smaller pool for pipelining\n\t\t}\n\t\tpipelinePoolName := opt.Addr + \"_\" + uniqueID + \"_pipeline\"\n\t\tc.pipelinePoolName = pipelinePoolName\n\t\tc.pipelinePool, err = newConnPool(pipelineOpt, c.dialHook, pipelinePoolName)\n\t\tif err != nil {\n\t\t\tpanic(fmt.Errorf(\"redis: failed to create pipeline connection pool: %w\", err))\n\t\t}\n\t}\n\n\tif opt.StreamingCredentialsProvider != nil {\n\t\tc.streamingCredentialsManager = streaming.NewManager(c.connPool, c.opt.PoolTimeout)\n\t\tc.connPool.AddPoolHook(c.streamingCredentialsManager.PoolHook())\n\t\tif c.pipelinePool != nil {\n\t\t\tc.pipelinePool.AddPoolHook(c.streamingCredentialsManager.PoolHook())\n\t\t}\n\t}\n\n\t// CSC wiring (SharedTracking): shared cache + per-connection CLIENT TRACKING +\n\t// background drainer. attachCSC is the strategy dispatch entry.\n\tif opt.Protocol == 3 {\n\t\tvar cache Cache\n\t\tif explicit := opt.ClientSideCache; explicit != nil {\n\t\t\tcache = explicit\n\t\t} else if cfg := opt.ClientSideCacheConfig; cfg != nil {","sourceCodeStart":1969,"sourceCodeEnd":2005,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/redis.go#L1969-L2005","documentation":"Panicked from NewClient when a separate pipeline connection pool is requested (PipelineReadBufferSize or PipelineWriteBufferSize > 0) and newConnPool(pipelineOpt, dialHook, name) fails. The pipeline pool has its own (cloned) options and default size of 10; failure is fatal.","triggerScenarios":"Setting PipelineReadBufferSize/PipelineWriteBufferSize > 0 and the resulting pipelineOpt produces an invalid pool configuration (e.g. PipelinePoolSize <= 0 combined with the clone logic, or buffer size below the RESP3 minimum clamp).","commonSituations":"PipelinePoolSize set to 0 or negative; PipelineReadBufferSize set very small causing the RESP3 minimum clamp to interact unexpectedly; a hook or dialer shared with the main pool failing during the pipeline pool build.","solutions":["Wrap NewClient in recover().","If PipelinePoolSize is set, ensure it is > 0; if unset, the default of 10 is used.","Validate PipelineReadBufferSize/PipelineWriteBufferSize are positive and reasonable (>= proto.MinRESP3ReadBufferSize when Protocol == 3).","Temporarily remove the pipeline buffer options to confirm the pipeline pool is the failing component."],"exampleFix":"// before\nopt := &redis.Options{\n    Addr: addr,\n    PipelineReadBufferSize: 16,\n    PipelinePoolSize:      0, // intentionally unset is fine; negative breaks\n}\n\n// after\nopt := &redis.Options{\n    Addr: addr,\n    PipelineReadBufferSize: 64 * 1024,\n}","handlingStrategy":"validation","validationCode":"if (opt.PipelineReadBufferSize > 0 || opt.PipelineWriteBufferSize > 0) {\n    if opt.PipelineReadBufferSize > 0 && opt.Protocol == 3 &&\n        opt.PipelineReadBufferSize < proto.MinRESP3ReadBufferSize {\n        return errors.New(\"PipelineReadBufferSize below RESP3 minimum\")\n    }\n    if opt.PipelinePoolSize < 0 {\n        return errors.New(\"PipelinePoolSize must be >= 0\")\n    }\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        return nil, fmt.Errorf(\"redis NewClient (pipeline pool) failed: %v\", r)\n    }\n}()\nreturn redis.NewClient(opt), nil","preventionTips":["Only set PipelineReadBufferSize/PipelineWriteBufferSize when you need larger pipeline buffers.","Leave PipelinePoolSize unset to accept the default of 10.","Wrap NewClient in recover() so pipeline-pool misconfiguration is catchable."],"tags":["pool","pipeline","config","initialization","panic"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}