juanfont/headscale · error
creating Docker client: %w
Error message
creating Docker client: %w
What it means
client.NewClientWithOpts failed while constructing the Docker SDK client in NewStatsCollector. The client builder resolves its endpoint from the active docker context's endpoint host or DOCKER_HOST/DOCKER_TLS_SERVERCERT env vars (see createDockerClient at cmd/hi/docker.go:453) and errors when the host string is malformed or an unsupported protocol scheme is given. Note the SDK client is lazy — this failure is about client construction options, not daemon reachability.
Source
Thrown at cmd/hi/stats.go:54
CPUUsage float64 // CPU usage percentage
MemoryMB float64 // Memory usage in MB
}
// StatsCollector manages collection of container statistics.
type StatsCollector struct {
client *client.Client
containers map[string]*ContainerStats
stopChan chan struct{}
wg sync.WaitGroup
mutex sync.RWMutex
collectionStarted bool
}
// NewStatsCollector creates a new stats collector instance.
func NewStatsCollector(ctx context.Context) (*StatsCollector, error) {
cli, err := createDockerClient(ctx)
if err != nil {
return nil, fmt.Errorf("creating Docker client: %w", err)
}
return &StatsCollector{
client: cli,
containers: make(map[string]*ContainerStats),
stopChan: make(chan struct{}),
}, nil
}
// StartCollection begins monitoring all containers and collecting stats for hs- and ts- containers with matching run ID.
func (sc *StatsCollector) StartCollection(ctx context.Context, runID string, verbose bool) error {
sc.mutex.Lock()
defer sc.mutex.Unlock()
if sc.collectionStarted {
return ErrStatsCollectionAlreadyStarted
}
View on GitHub (pinned to 565fd254d0)
Solutions
- Print and fix the environment: `echo $DOCKER_HOST` — it must be a valid scheme like unix:///var/run/docker.sock or tcp://host:2375
- Check `docker context ls` and `docker context use default` to discard a broken context
- Unset stale DOCKER_TLS_SERVERCERT/DOCKER_CERT_PATH values: `env -u DOCKER_TLS_SERVERCERT -u DOCKER_CERT_PATH go run ./cmd/hi ...`
- Verify plain `docker info` works with the same environment
Example fix
# before export DOCKER_HOST=:2375 # malformed, no scheme go run ./cmd/hi run "TestACL" # after export DOCKER_HOST=tcp://127.0.0.1:2375 go run ./cmd/hi run "TestACL"
Defensive patterns
Strategy: validation
Validate before calling
if host := os.Getenv("DOCKER_HOST"); host != "" {
u, err := url.Parse(host)
if err != nil || (u.Scheme != "unix" && u.Scheme != "tcp" && u.Scheme != "npipe") {
return fmt.Errorf("invalid DOCKER_HOST %q", host)
}
}
_ = exec.LookPath("docker") // sanity: CLI sees the same daemon Try / catch
cli, err := createDockerClient(ctx)
if err != nil {
// construction errors are config/env problems — print env and docker context, do not retry
return nil, fmt.Errorf("creating Docker client: %w (check DOCKER_HOST=%q and `docker context ls`)", err, os.Getenv("DOCKER_HOST"))
} Prevention
- Keep DOCKER_HOST either unset (local socket) or a fully-qualified unix:///tcp:// URL
- Reset to a known context with `docker context use default` when switching daemons
- Ensure `docker info` works in the same shell before running hi
When it happens
Trigger: NewClientWithOpts rejecting an invalid host (bad DOCKER_HOST like 'tcp://:2375' or a scheme the SDK cannot handle, e.g. missing tcp://, npipe on Linux), unreadable TLS cert files, or an API version negotiation opt that fails to parse environment values.
Common situations: DOCKER_HOST set to a typo'd or Windows-style endpoint on Linux; a docker context whose endpoint metadata is malformed; leftover DOCKER_* env vars from a remote-daemon setup; running where the context config in ~/.docker/contexts is corrupted.
Related errors
- resolving registry auth: %w
- writing headscale config to container: %w
- must be a positive duration
- checkPeriod is only valid with action "check"
- invalid localpart format, must be localpart:*@<domain>
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/2f0d5623da176fa7.
Report an issue: GitHub.