{"record":{"id":"fb8de8af885c0e9b","repo":"cloudflare/cloudflared","slug":"failed-to-parse-host","errorCode":null,"errorMessage":"failed to parse Host","messagePattern":"failed to parse Host","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cloudflared/access/validation.go","lineNumber":64,"sourceCode":"// certain expectations from the URL.\n// Will convert all HTTP URLs to HTTPS\nfunc parseURL(input string) (*url.URL, error) {\n\tif input == \"\" {\n\t\treturn nil, errors.New(\"no input provided\")\n\t}\n\tif !strings.HasPrefix(input, \"https://\") && !strings.HasPrefix(input, \"http://\") {\n\t\tinput = fmt.Sprintf(\"https://%s\", input)\n\t}\n\tinput = bracketBareIPv6(input)\n\turl, err := url.ParseRequestURI(input)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse as URL: %w\", err)\n\t}\n\tif url.Scheme != \"https\" {\n\t\turl.Scheme = \"https\"\n\t}\n\tif url.Host == \"\" {\n\t\treturn nil, errors.New(\"failed to parse Host\")\n\t}\n\thost, err := httpguts.PunycodeHostPort(url.Host)\n\tif err != nil || host == \"\" {\n\t\treturn nil, err\n\t}\n\tif !httpguts.ValidHostHeader(host) {\n\t\treturn nil, errors.New(\"invalid Host provided\")\n\t}\n\turl.Host = host\n\treturn url, nil\n}\n","sourceCodeStart":46,"sourceCodeEnd":76,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cmd/cloudflared/access/validation.go#L46-L76","documentation":"After parseURL prefixes https:// and parses the input with url.ParseRequestURI, it checks that a Host component was actually captured. Input that Go's parser accepts but that yields no host (e.g. a bare path, protocol-only string, or whitespace) triggers this error, because an Access application URL must have a hostname to route to.","triggerScenarios":"`cloudflared access ssh /just/a/path`, `https://` with no host, or input containing only whitespace/special characters that parses as a URL without a Host portion.","commonSituations":"Truncated URLs from variable interpolation (`https://$BUCKET` with BUCKET empty); pasting a URL and losing the hostname; passing a path instead of a host.","solutions":["Provide a full hostname, e.g. `app.example.com` or `https://app.example.com`.","Echo the exact value being passed to confirm it is non-empty and includes a host.","If building the URL in a script, validate the host segment before calling cloudflared."],"exampleFix":"// before\nurl := \"https://\" + os.Getenv(\"SUBDOMAIN\") // empty -> no Host\n// after\nif os.Getenv(\"SUBDOMAIN\") == \"\" { return errors.New(\"SUBDOMAIN is required\") }\nurl := \"https://\" + os.Getenv(\"SUBDOMAIN\") + \".example.com\"","handlingStrategy":"validation","validationCode":"u, err := url.ParseRequestURI(input)\nif err != nil || u.Host == \"\" {\n    return errors.New(\"input must include a hostname, e.g. https://app.example.com\")\n}","typeGuard":"func hasHost(u *url.URL) bool { return u != nil && u.Host != \"\" }","tryCatchPattern":"url, err := parseURL(input)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to parse Host\") {\n        return fmt.Errorf(\"%q is not a usable hostname for access; include a host like app.example.com\", input)\n    }\n    return err\n}","preventionTips":["Ensure env vars that compose the hostname are set before interpolation.","Pass fully-formed URLs (https://host) rather than paths or fragments.","Test the hostname resolves (dig/host) before feeding it to access commands."],"tags":["cli","url","validation"],"backgroundTag":"invalid-url-format","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}