wtfutil/wtf · error
could not create client: %w
Error message
could not create client: %w
What it means
NewWidget builds the Docker client with client.NewClientWithOpts(client.FromEnv), which reads DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH etc. from the environment. If client construction fails (invalid DOCKER_HOST URL, missing/malformed TLS config, unparsable env), the error is stored in the widget's displayBuffer as "could not create client". This happens before any daemon call — it is a configuration failure.
Source
Thrown at modules/docker/widget.go:28
type Widget struct {
view.TextWidget
cli *client.Client
settings *Settings
displayBuffer string
}
func NewWidget(tviewApp *tview.Application, redrawChan chan bool, pages *tview.Pages, settings *Settings) *Widget {
widget := Widget{
TextWidget: view.NewTextWidget(tviewApp, redrawChan, pages, settings.Common),
settings: settings,
}
widget.View.SetScrollable(true)
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
widget.displayBuffer = fmt.Errorf("could not create client: %w", err).Error()
} else {
widget.cli = cli
}
widget.refreshDisplayBuffer()
return &widget
}
/* -------------------- Exported Functions -------------------- */
func (widget *Widget) Refresh() {
widget.refreshDisplayBuffer()
widget.Redraw(widget.display)
}
/* -------------------- Unexported Functions -------------------- */
View on GitHub (pinned to bb838c1ccb)
Solutions
- Validate DOCKER_HOST parses as a URL: docker -H "$DOCKER_HOST" info.
- Fix the scheme — use tcp://, unix://, or npipe:// prefixes explicitly.
- If DOCKER_TLS_VERIFY=1, confirm DOCKER_CERT_PATH contains ca.pem, cert.pem, key.pem.
- Unset DOCKER_* vars to fall back to the default local socket if you intend local usage.
Example fix
// before
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
widget.displayBuffer = fmt.Errorf("could not create client: %w", err).Error()
}
// after
host := os.Getenv("DOCKER_HOST")
if host != "" && !strings.Contains(host, "://") {
host = "tcp://" + host
os.Setenv("DOCKER_HOST", host)
}
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
widget.displayBuffer = fmt.Errorf("could not create client: %w", err).Error()
} Defensive patterns
Strategy: validation
Validate before calling
host := os.Getenv("DOCKER_HOST")
if host != "" {
if _, err := url.Parse(host); err != nil || !strings.Contains(host, "://") {
return fmt.Errorf("invalid DOCKER_HOST %q: must be a URL like tcp://host:2375 or unix:///path", host)
}
}
if os.Getenv("DOCKER_TLS_VERIFY") != "" {
for _, f := range []string{"ca.pem", "cert.pem", "key.pem"} {
if _, err := os.Stat(filepath.Join(os.Getenv("DOCKER_CERT_PATH"), f)); err != nil {
return fmt.Errorf("missing TLS cert %s in DOCKER_CERT_PATH", f)
}
}
} Type guard
func validDockerHost(host string) bool {
u, err := url.Parse(host)
return err == nil && u.Scheme != "" && (u.Scheme == "unix" || u.Scheme == "tcp" || u.Scheme == "npipe" || u.Scheme == "ssh")
} Try / catch
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
widget.displayBuffer = fmt.Sprintf("docker client config invalid: %v — check DOCKER_HOST/DOCKER_CERT_PATH", err)
return
} Prevention
- Always use fully qualified DOCKER_HOST values (scheme included).
- Run `docker -H "$DOCKER_HOST" info` to validate env config before launching the app.
- Unset DOCKER_* variables when you intend to use the default local socket.
When it happens
Trigger: client.FromEnv fails: DOCKER_HOST is not a valid URL (e.g., "myhost" instead of "tcp://myhost:2375"), DOCKER_CERT_PATH files missing/unreadable with DOCKER_TLS_VERIFY=1, or unsupported scheme.
Common situations: Copy-pasted DOCKER_HOST from a teammate with a typo, switched from Docker Desktop to colima/podman without updating the socket path, missing cert files after machine migration, or env vars set in one shell but not the one launching the app.
Related errors
- failed to initialize Azure session: %w
- invalid base URL: %w
- could not get docker system info: %w
- could not get disk usage: %w
- could not get container list: %w
AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03).
Data as JSON: /api/errors/9980bb886076b006.
Report an issue: GitHub.