go-redis/redis · error
redis: connection pool timeout
Error message
redis: connection pool timeout
What it means
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.
Source
Thrown at internal/pool/pool.go:65
// MetricStateIdle indicates the connection is idle in the pool,
// ready to be acquired.
MetricStateIdle = "idle"
// MetricStateUsed indicates the connection is currently being used
// by a client operation.
MetricStateUsed = "used"
)
var (
// ErrClosed performs any operation on the closed client will return this error.
ErrClosed = errors.New("redis: client is closed")
// ErrPoolExhausted is returned from a pool connection method
// when the maximum number of database connections in the pool has been reached.
ErrPoolExhausted = errors.New("redis: connection pool exhausted")
// ErrPoolTimeout timed out waiting to get a connection from the connection pool.
ErrPoolTimeout = errors.New("redis: connection pool timeout")
// ErrConnUnusableTimeout is returned when a connection is not usable and we timed out trying to mark it as unusable.
ErrConnUnusableTimeout = errors.New("redis: timed out trying to mark connection as unusable")
// errHookRequestedRemoval is returned when a hook requests connection removal.
errHookRequestedRemoval = errors.New("hook requested removal")
// errConnNotPooled is returned when trying to return a non-pooled connection to the pool.
errConnNotPooled = errors.New("connection not pooled")
// errConnEvictedIdle is passed to OnRemove hooks when a pooled connection is evicted on
// Put because the idle pool is already at MaxIdleConns.
errConnEvictedIdle = errors.New("connection evicted: idle pool at capacity")
// metricCallbackMu protects all global metric callback functions for thread-safe access.
metricCallbackMu sync.RWMutex
// Global metric callbacks for connection state changesView on GitHub (pinned to 36d97525cd)
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.
Example fix
// before
opt := &redis.Options{Addr: addr, PoolTimeout: 1 * time.Second}
// after
opt := &redis.Options{
Addr: addr,
PoolSize: 64,
MinIdleConns: 16,
PoolTimeout: 10 * time.Second,
} Defensive patterns
Strategy: retry
Validate before calling
// Choose PoolTimeout >= expected worst-case command latency.
opts := &redis.Options{Addr: addr, PoolSize: 64, PoolTimeout: 10 * time.Second} Try / catch
for i := 0; i < 3; i++ {
err := client.Get(ctx, key).Err()
if err == nil { break }
if errors.Is(err, redis.ErrPoolTimeout) {
time.Sleep(time.Duration(i+1) * 50 * time.Millisecond)
continue
}
return err
} Prevention
- Increase PoolSize and PoolTimeout to absorb transient saturation.
- Shorten or shard slow/blocking commands.
- Add MinIdleConns to keep the pool warm.
When it happens
Trigger: 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.
Common situations: Slow Lua scripts, BLPOP/MULTI-EXEC holding conns, network latency spikes, or PoolTimeout set too low relative to command latency.
Related errors
- redis: connection pool exhausted
- redis: timed out trying to mark connection as unusable
- relaxed timeout must be greater than 0
- redis: connection not available
- redis: connection not available for write operation
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/1b5b7a2fcbdae5c0.json.
Report an issue: GitHub.