{"record":{"id":"71dbb4bf4af96184","repo":"docker/cli","slug":"invalid-ssh-url-w","errorCode":null,"errorMessage":"invalid SSH URL: %w","messagePattern":"invalid SSH URL: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/connhelper/ssh/ssh.go","lineNumber":22,"sourceCode":"import (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/url\"\n\n\t\"github.com/docker/cli/cli/connhelper/internal/syntax\"\n)\n\n// ParseURL creates a [Spec] from the given ssh URL. It returns an error if\n// the URL is using the wrong scheme, contains fragments, query-parameters,\n// or contains a password.\nfunc ParseURL(daemonURL string) (*Spec, error) {\n\tu, err := url.Parse(daemonURL)\n\tif err != nil {\n\t\tvar urlErr *url.Error\n\t\tif errors.As(err, &urlErr) {\n\t\t\terr = urlErr.Unwrap()\n\t\t}\n\t\treturn nil, fmt.Errorf(\"invalid SSH URL: %w\", err)\n\t}\n\treturn NewSpec(u)\n}\n\n// NewSpec creates a [Spec] from the given ssh URL's properties. It returns\n// an error if the URL is using the wrong scheme, contains fragments,\n// query-parameters, or contains a password.\nfunc NewSpec(sshURL *url.URL) (*Spec, error) {\n\ts, err := newSpec(sshURL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid SSH URL: %w\", err)\n\t}\n\treturn s, nil\n}\n\nfunc newSpec(u *url.URL) (*Spec, error) {\n\tif u == nil {\n\t\treturn nil, errors.New(\"URL is nil\")","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/connhelper/ssh/ssh.go#L4-L40","documentation":"Raised by ssh.ParseURL (ssh.go:16-22) when Go's net/url.Parse cannot parse the daemon URL at all. If the error is a *url.Error it is unwrapped to its cause before being wrapped as `invalid SSH URL: <err>`. This is a hard parse failure, distinct from semantic validation done later in newSpec.","triggerScenarios":"Calling ssh.ParseURL(daemonURL) where url.Parse(daemonURL) returns an error — e.g. control characters, an unencoded space, an invalid escape sequence (`%zz`), or a missing/illegal authority that the URL parser rejects.","commonSituations":"DOCKER_HOST contains an ssh URL with unencoded special characters, a malformed percent-encoding, or stray whitespace from shell quoting. Copy-pasting a URL with spaces or control characters triggers it.","solutions":["Inspect the wrapped url.Parse error for the specific token/position at fault.","Percent-encode any special characters in the URL (spaces as %20, etc.) or remove them.","Quote the DOCKER_HOST value in the shell to avoid word-splitting: `export DOCKER_HOST='ssh://user@host'`.","Test the URL with `python -c 'import urllib.parse; urllib.parse.urlparse(...)'` or by hand."],"exampleFix":"# before — stray space / bad encoding\nexport DOCKER_HOST='ssh://user @host%zz'\n# after — clean, encoded URL\nexport DOCKER_HOST='ssh://user@host'","handlingStrategy":"validation","validationCode":"// Reject URLs net/url cannot parse.\nif _, err := url.Parse(daemonURL); err != nil {\n    return fmt.Errorf(\"DOCKER_HOST is not a valid URL: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"spec, err := ssh.ParseURL(daemonURL)\nif err != nil {\n    return fmt.Errorf(\"cannot parse ssh host: %w\", err)\n}","preventionTips":["Always quote DOCKER_HOST in shell assignments.","Percent-encode special characters instead of leaving them raw.","Validate URLs in CI configuration."],"tags":["connhelper","ssh","url","parse"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}