docker/cli · warning
timeout waiting for stats
Error message
timeout waiting for stats
What it means
Set on a stats entry by the stats collector when no stats update is received from the daemon within 2 seconds (time.After(2*time.Second) in the select loop at stats_helpers.go:151). It indicates the streaming stats response stalled; the entry is marked with an error and reset. Common with very busy daemons, network hiccups, or containers that just stopped.
Solutions
- Retry the stats command; transient stalls often clear.
- Check daemon health and load (`docker info`, host CPU/mem); reduce load or restart the daemon if saturated.
- For remote daemons, verify network latency/bandwidth and avoid buffering proxies between client and daemon.
- Use `docker stats --no-stream` for a one-shot read that does not depend on a continuous stream.
Example fix
// before docker stats # stalls >2s over a remote TCP socket // after docker stats --no-stream
Defensive patterns
Strategy: retry
Validate before calling
// For one-shot reads, request non-streaming stats to avoid the 2s stall window. options.NoStream = true
Try / catch
// Retry streaming stats a few times; fall back to --no-stream on repeated stalls.
const maxRetries = 3
var err error
for i := 0; i < maxRetries; i++ {
err = runStats(ctx, cli, options)
if err == nil {
break
}
if i == maxRetries-1 {
options.NoStream = true // fall back to one-shot
err = runStats(ctx, cli, options)
}
} Prevention
- Use --no-stream for single snapshots to avoid the streaming timeout window.
- Monitor daemon load; high load is a common cause of stalled stats streams.
- For remote daemons, prefer low-latency, non-buffering connections (avoid HTTP proxies on the path).
When it happens
Trigger: Running `docker stats` (streaming) against a daemon that stops sending updates for >2s — e.g. high daemon load, slow remote socket (TCP/SSH), the container exiting mid-stream, or a proxy/load-balancer buffering the stream.
Common situations: Remote Docker hosts over slow/unstable TCP or SSH tunnels. Daemon under heavy CPU/memory pressure. Transient container exits during stats collection. TLS/VPN overhead inflating latency.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- conflicting options: cannot specify both --link-local-ip…
- no name set for network
- network-scoped aliases are only supported for user-defined…
- links are only supported for user-defined networks
- filtering is not supported when specifying a list of…
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/4cd8695031d8442f.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/container/stats_helpers.go:154
NetworkRx: netRx,
NetworkTx: netTx,
BlockRead: float64(blkRead),
BlockWrite: float64(blkWrite),
PidsCurrent: v.PidsStats.Current,
})
}
u <- nil
if !streamStats {
return
}
}
}()
for {
select {
case <-time.After(2 * time.Second):
// zero out the values if we have not received an update within
// the specified duration.
s.SetErrorAndReset(errors.New("timeout waiting for stats"))
// if this is the first stat you get, release WaitGroup
if !getFirst {
getFirst = true
waitFirst.Done()
}
case err := <-u:
s.SetError(err)
if errors.Is(err, io.EOF) {
return
}
if err != nil {
continue
}
// if this is the first stat you get, release WaitGroup
if !getFirst {
getFirst = true
waitFirst.Done()
}View on GitHub (pinned to 4f84911bfe)