{"id":"1b5b7a2fcbdae5c0","repo":"go-redis/redis","slug":"redis-connection-pool-timeout","errorCode":null,"errorMessage":"redis: connection pool timeout","messagePattern":"redis: connection pool timeout","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pool/pool.go","lineNumber":65,"sourceCode":"\t// MetricStateIdle indicates the connection is idle in the pool,\n\t// ready to be acquired.\n\tMetricStateIdle = \"idle\"\n\n\t// MetricStateUsed indicates the connection is currently being used\n\t// by a client operation.\n\tMetricStateUsed = \"used\"\n)\n\nvar (\n\t// ErrClosed performs any operation on the closed client will return this error.\n\tErrClosed = errors.New(\"redis: client is closed\")\n\n\t// ErrPoolExhausted is returned from a pool connection method\n\t// when the maximum number of database connections in the pool has been reached.\n\tErrPoolExhausted = errors.New(\"redis: connection pool exhausted\")\n\n\t// ErrPoolTimeout timed out waiting to get a connection from the connection pool.\n\tErrPoolTimeout = errors.New(\"redis: connection pool timeout\")\n\n\t// ErrConnUnusableTimeout is returned when a connection is not usable and we timed out trying to mark it as unusable.\n\tErrConnUnusableTimeout = errors.New(\"redis: timed out trying to mark connection as unusable\")\n\n\t// errHookRequestedRemoval is returned when a hook requests connection removal.\n\terrHookRequestedRemoval = errors.New(\"hook requested removal\")\n\n\t// errConnNotPooled is returned when trying to return a non-pooled connection to the pool.\n\terrConnNotPooled = errors.New(\"connection not pooled\")\n\n\t// errConnEvictedIdle is passed to OnRemove hooks when a pooled connection is evicted on\n\t// Put because the idle pool is already at MaxIdleConns.\n\terrConnEvictedIdle = errors.New(\"connection evicted: idle pool at capacity\")\n\n\t// metricCallbackMu protects all global metric callback functions for thread-safe access.\n\tmetricCallbackMu sync.RWMutex\n\n\t// Global metric callbacks for connection state changes","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/internal/pool/pool.go#L47-L83","documentation":"pool.ErrPoolTimeout is returned when waiting for a free connection exceeds Options.PoolTimeout (pool.go:64-65). It is produced by the semaphore acquire in waitForTurn (pool.go:1179) and the get path (pool.go:876/1238/1253). It means the pool is saturated AND the configured wait budget elapsed.","triggerScenarios":"All pool connections busy for longer than PoolTimeout (default ReadTimeout or 10s), e.g. many slow commands or a downstream stall, so a goroutine times out waiting in the wantConn queue.","commonSituations":"Slow Lua scripts, BLPOP/MULTI-EXEC holding conns, network latency spikes, or PoolTimeout set too low relative to command latency.","solutions":["Increase Options.PoolSize to reduce queueing.","Increase Options.PoolTimeout (or set ReadTimeout high enough) to tolerate transient stalls.","Identify and speed up slow/blocking commands; avoid holding connections across blocking calls.","Add MinIdleConns so the pool warms up and dials proactively."],"exampleFix":"// before\nopt := &redis.Options{Addr: addr, PoolTimeout: 1 * time.Second}\n// after\nopt := &redis.Options{\n    Addr:         addr,\n    PoolSize:     64,\n    MinIdleConns: 16,\n    PoolTimeout:  10 * time.Second,\n}","handlingStrategy":"retry","validationCode":"// Choose PoolTimeout >= expected worst-case command latency.\nopts := &redis.Options{Addr: addr, PoolSize: 64, PoolTimeout: 10 * time.Second}","typeGuard":null,"tryCatchPattern":"for i := 0; i < 3; i++ {\n    err := client.Get(ctx, key).Err()\n    if err == nil { break }\n    if errors.Is(err, redis.ErrPoolTimeout) {\n        time.Sleep(time.Duration(i+1) * 50 * time.Millisecond)\n        continue\n    }\n    return err\n}","preventionTips":["Increase PoolSize and PoolTimeout to absorb transient saturation.","Shorten or shard slow/blocking commands.","Add MinIdleConns to keep the pool warm."],"tags":["pool","timeout","configuration","concurrency"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}