cloudflare/cloudflared · error

failed to parse Host

Error message

failed to parse Host

What it means

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.

Source

Thrown at cmd/cloudflared/access/validation.go:64

// certain expectations from the URL.
// Will convert all HTTP URLs to HTTPS
func parseURL(input string) (*url.URL, error) {
	if input == "" {
		return nil, errors.New("no input provided")
	}
	if !strings.HasPrefix(input, "https://") && !strings.HasPrefix(input, "http://") {
		input = fmt.Sprintf("https://%s", input)
	}
	input = bracketBareIPv6(input)
	url, err := url.ParseRequestURI(input)
	if err != nil {
		return nil, fmt.Errorf("failed to parse as URL: %w", err)
	}
	if url.Scheme != "https" {
		url.Scheme = "https"
	}
	if url.Host == "" {
		return nil, errors.New("failed to parse Host")
	}
	host, err := httpguts.PunycodeHostPort(url.Host)
	if err != nil || host == "" {
		return nil, err
	}
	if !httpguts.ValidHostHeader(host) {
		return nil, errors.New("invalid Host provided")
	}
	url.Host = host
	return url, nil
}

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Provide a full hostname, e.g. `app.example.com` or `https://app.example.com`.
  2. Echo the exact value being passed to confirm it is non-empty and includes a host.
  3. If building the URL in a script, validate the host segment before calling cloudflared.

Example fix

// before
url := "https://" + os.Getenv("SUBDOMAIN") // empty -> no Host
// after
if os.Getenv("SUBDOMAIN") == "" { return errors.New("SUBDOMAIN is required") }
url := "https://" + os.Getenv("SUBDOMAIN") + ".example.com"
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.ParseRequestURI(input)
if err != nil || u.Host == "" {
    return errors.New("input must include a hostname, e.g. https://app.example.com")
}

Type guard

func hasHost(u *url.URL) bool { return u != nil && u.Host != "" }

Try / catch

url, err := parseURL(input)
if err != nil {
    if strings.Contains(err.Error(), "failed to parse Host") {
        return fmt.Errorf("%q is not a usable hostname for access; include a host like app.example.com", input)
    }
    return err
}

Prevention

When it happens

Trigger: `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.

Common situations: Truncated URLs from variable interpolation (`https://$BUCKET` with BUCKET empty); pasting a URL and losing the hostname; passing a path instead of a host.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/fb8de8af885c0e9b. Report an issue: GitHub.