docker/cli · error
invalid host
Error message
invalid host: %w
What it means
Raised in Spec.args (ssh.go:129-131) when the host portion of the ssh URL cannot be POSIX-shell-quoted by syntax.Quote. The host is taken from u.Hostname() and passed as the final positional argument to ssh after `--`; if it contains bytes the quoting library rejects, this wraps the error.
Solutions
- Inspect the hostname in the DOCKER_HOST URL for invisible/control characters.
- Re-enter the hostname as plain ASCII (letters, digits, dots, hyphens).
- Percent-encode any legitimately special characters in the URL host.
Example fix
# before — invisible control char in host export DOCKER_HOST='ssh://user@host<x00>.example.com' # after export DOCKER_HOST='ssh://user@host.example.com'
Defensive patterns
Strategy: validation
Validate before calling
u, _ := url.Parse(daemonURL)
if u != nil {
h := u.Hostname()
if h == "" {
return errors.New("ssh URL host is empty")
}
for _, r := range h {
if r < 0x20 || r > 0x7e {
return errors.New("ssh URL host contains control characters")
}
}
} Try / catch
args, err := spec.Args(remote...)
if err != nil {
return fmt.Errorf("cannot build ssh args (bad host?): %w", err)
} Prevention
- Restrict DOCKER_HOST hostnames to printable ASCII (letters, digits, dots, hyphens).
- Sanitize env-sourced values for hidden characters.
- Add a CI lint for DOCKER_HOST format.
When it happens
Trigger: Spec.args/Args/Command is called after building a Spec from a URL whose Host field contains characters syntax.Quote cannot handle, such as a NUL byte or other non-printable control character that cannot appear in a safe POSIX token.
Common situations: A DOCKER_HOST ssh URL whose hostname has a hidden control byte (often from a corrupted env var, a templating bug, or a paste with invisible characters). In normal operation hostnames are clean and this error is never seen.
Related errors
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/05b76519580ea761.
Report an issue: GitHub.
Appendix: source
Thrown at cli/connhelper/ssh/ssh.go:131
}
args = append(args, "-l", usr)
}
if sp.Port != "" {
// Quote port, as it's obtained from the URL.
port, err := syntax.Quote(sp.Port, syntax.LangPOSIX)
if err != nil {
return nil, fmt.Errorf("invalid port: %w", err)
}
args = append(args, "-p", port)
}
// We consider "sshFlags" to be "trusted", and set from code only,
// as they are not parsed from the DOCKER_HOST URL.
args = append(args, sshFlags...)
host, err := syntax.Quote(sp.Host, syntax.LangPOSIX)
if err != nil {
return nil, fmt.Errorf("invalid host: %w", err)
}
return append(args, "--", host), nil
}
// Command returns the ssh flags and arguments to execute a command
// (remoteCommandAndArgs) on the remote host. Where needed, it quotes
// values passed in remoteCommandAndArgs to account for ssh executing
// the remote command in a shell. It returns an error if no remote command
// is passed, or when unable to quote the remote command.
//
// Important: to preserve backward-compatibility, Command does not currently
// perform sanitization or quoting on the sshFlags and callers are expected
// to sanitize this argument.
func (sp *Spec) Command(sshFlags []string, remoteCommandAndArgs ...string) ([]string, error) {
if len(remoteCommandAndArgs) == 0 {
return nil, errors.New("no remote command specified")
}View on GitHub (pinned to 4f84911bfe)