{"record":{"id":"a48f1738a17b607a","repo":"redis/go-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":2132,"sourceCode":"\tc.connPool, err = newConnPool(opt, c.dialHook, mainPoolName)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"redis: failed to create connection pool: %w\", err))\n\t}\n\tc.pubSubPool, err = newPubSubPool(opt, c.dialHook, pubsubPoolName)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"redis: failed to create pubsub pool: %w\", err))\n\t}\n\n\t// Create the dedicated pipeline pool unconditionally, like pubSubPool: it\n\t// is pure burst capacity (no pre-dialing, small cap, larger buffers — see\n\t// pipelinePoolOptions), so an unused pipeline pool holds zero connections\n\t// and costs nothing. Pipelines stop competing with regular commands for\n\t// main-pool connections; a burst wider than the pool's cap spills back to\n\t// the main pool (see withPipelineConn). PipelinePoolSize < 0 opts out.\n\tif opt.PipelinePoolSize >= 0 {\n\t\tref, err := c.buildPipelinePool(opt.Addr + \"_\" + uniqueID + \"_pipeline\")\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\tc.pipelinePool = ref\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 pp := c.getPipelinePool(); pp != nil {\n\t\t\tpp.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","sourceCodeStart":2114,"sourceCodeEnd":2150,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/redis.go#L2114-L2150","documentation":"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.","triggerScenarios":"Calling redis.NewClient with Options.PipelinePoolSize >= 0 (opt-in) while other pool options cause buildPipelinePool to fail, at redis.go:2132.","commonSituations":"Setting PipelinePoolSize explicitly for the first time and combining it with an invalid main-pool/buffer option; validating config only partially.","solutions":["Read the wrapped cause (%w) to find the invalid option","If pipelines are not needed, set Options.PipelinePoolSize = -1 to opt out of the pool entirely","Fix the conflicting redis.Options field"],"exampleFix":"// before\nopt := &redis.Options{Addr: addr, PipelinePoolSize: 16, ReadBufferSize: -32}\n// after\nopt := &redis.Options{Addr: addr, PipelinePoolSize: 16} // valid buffers/default","handlingStrategy":"validation","validationCode":"if opt.PipelinePoolSize > 0 && opt.PoolSize <= 0 { return errors.New(\"PipelinePoolSize requires a valid PoolSize\") }\nclient := redis.NewClient(opt)","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        err = fmt.Errorf(\"redis client init failed: %v\", r)\n    }\n}()","preventionTips":["Set PipelinePoolSize = -1 if pipelines need no dedicated pool","Introduce PipelinePoolSize gradually and test init in CI","Keep pipeline pool smaller than the main pool"],"tags":["go","client-init","panic","pipeline"],"backgroundTag":"invalid-pool-configuration","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}