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

  1. Inspect the hostname in the DOCKER_HOST URL for invisible/control characters.
  2. Re-enter the hostname as plain ASCII (letters, digits, dots, hyphens).
  3. 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

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)