jesseduffield/lazydocker · error
ssh tunneled socket never became available: %w
Error message
ssh tunneled socket never became available: %w
What it means
After starting `ssh -L`, createDockerHostTunnel waits up to 8 seconds (retrySocketDial ticks every second) for the local unix socket to accept a connection. This error means the tunnel process started but the socket never became dialable before the context deadline — the %w chain ends in context.DeadlineExceeded. It distinguishes 'ssh could not even start' from 'ssh started but the forward never worked'.
Source
Thrown at pkg/commands/ssh/ssh.go:108
if err != nil {
return nil, fmt.Errorf("create ssh tunnel tmp file: %w", err)
}
localSocket := path.Join(socketDir, "dockerhost.sock")
cmd, err := self.tunnelSSH(ctx, remoteHost, localSocket)
if err != nil {
return nil, fmt.Errorf("tunnel docker host over ssh: %w", err)
}
// set a reasonable timeout, then wait for the socket to dial successfully
// before attempting to create a new docker client
const socketTunnelTimeout = 8 * time.Second
ctx, cancel := context.WithTimeout(ctx, socketTunnelTimeout)
defer cancel()
err = self.retrySocketDial(ctx, localSocket)
if err != nil {
return nil, fmt.Errorf("ssh tunneled socket never became available: %w", err)
}
// construct the new DOCKER_HOST url with the proper scheme
newDockerHostURL := url.URL{Scheme: "unix", Path: localSocket}
return &tunneledDockerHost{
socketPath: newDockerHostURL.String(),
cmd: cmd,
oSCommand: self.oSCommand,
}, nil
}
// Attempt to dial the socket until it becomes available.
// The retry loop will continue until the parent context is canceled.
func (self *SSHHandler) retrySocketDial(ctx context.Context, socketPath string) error {
t := time.NewTicker(1 * time.Second)
defer t.Stop()
for {View on GitHub (pinned to 7e7aadc207)
Solutions
- Connect once manually to accept the host key: `ssh user@host echo ok` (fixes 'host key verification failed' stalls).
- Ensure non-interactive auth works: load keys with ssh-agent, or use a passphrase-less dedicated key via ~/.ssh/config.
- Confirm the remote socket path exists at /var/run/docker.sock (`ssh host ls /var/run/docker.sock`); for rootless docker, forward manually (`ssh -L /tmp/d.sock:/run/user/1000/docker.sock host -N &`) and set DOCKER_HOST=unix:///tmp/d.sock.
- On slow links, retry lazydocker — the 8s budget is fixed in code, so pre-warming the connection (manual ssh first) helps.
Example fix
# before DOCKER_HOST=ssh://user@newhost lazydocker # first connect: host-key prompt stalls -> timeout # after ssh user@newhost echo ok # accept host key once eval $(ssh-agent) && ssh-add DOCKER_HOST=ssh://user@newhost lazydocker
Defensive patterns
Strategy: retry
Validate before calling
// preflight the exact tunnel lazydocker will build
probe := exec.Command("ssh", "-o", "BatchMode=yes", "-L", "/tmp/probe.sock:/var/run/docker.sock", host, "-N")
if err := probe.Start(); err == nil {
defer probe.Process.Kill()
} else {
return fmt.Errorf("ssh tunnel preflight failed: %w", err)
} Try / catch
closer, err := sshHandler.LearnDockerHostShim()
if err != nil && strings.Contains(err.Error(), "never became available") {
time.Sleep(2 * time.Second)
closer, err = sshHandler.LearnDockerHostShim() // one retry: slow first-connect
} Prevention
- Connect manually to new hosts once to accept host keys before automating.
- Use BatchMode-friendly auth (agent-loaded keys) so ssh never blocks on prompts.
- Pre-warm slow links with a manual ssh session; lazydocker's 8s socket budget is fixed.
When it happens
Trigger: ssh is running but the forward is broken or too slow to establish: authentication stalls (passphrase prompt, disabled host-key acceptance in non-interactive mode), the remote /var/run/docker.sock does not exist, sshd on the remote refuses the forward (AllowTcpForwarding no / disabled unix forwarding), or the host is unreachable so ssh retries until the 8s budget runs out.
Common situations: First connection to a new host (host-key verification fails because lazydocker's ssh is non-interactive); key with passphrase and no agent; rootless docker on the remote (socket at /run/user/$UID/docker.sock, not /var/run/docker.sock); slow VPN/links exceeding 8 seconds to establish.
Related errors
- tunnel ssh docker host: %w
- override DOCKER_HOST to tunneled socket: %w
- create ssh tunnel tmp file: %w
- tunnel docker host over ssh: %w
- Cannot proceed until docker gives us more information about
AI-assisted analysis of jesseduffield/lazydocker@7e7aadc207 (2026-08-15).
Data as JSON: /api/errors/6fc00642a767b751.
Report an issue: GitHub.