cloudflare/cloudflared · error

failed to parse as URL: %w

Error message

failed to parse as URL: %w

What it means

parseURL normalizes user-supplied access input by defaulting the scheme to https:// (after bracketing bare IPv6 literals), then validates it with url.ParseRequestURI. If parsing fails it wraps the underlying error as 'failed to parse as URL'. It guarantees the access commands (ssh, app access, token generation) always operate on a well-formed HTTPS URL.

Source

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

		return prefix + "[" + host + "]" + rest[len(host):]
	}
	return input
}

// parseHostname will attempt to convert a user provided URL string into a string with some light error checking on
// 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. Check the wrapped cause (%w) for the exact parse failure — usually an invalid character or escape sequence.
  2. Pass a plain hostname or a properly percent-encoded URL; avoid spaces and raw special characters.
  3. Ensure the variable supplying the URL is set and non-empty in scripts (`"${URL:?URL not set}"`).
  4. Use url.PathEscape/url.QueryEscape for dynamic components before composing the input string.
  5. IPv6 hosts must be bracketed: [2001:db8::1] — though parseURL brackets bare IPv6, other malformed bracket forms still fail.

Example fix

// before
$ cloudflared access ssh --hostname "my host example.com"
// after
$ cloudflared access ssh --hostname my-host.example.com
Defensive patterns

Strategy: validation

Validate before calling

func validAccessURL(input string) bool {
	if input == "" { return false }
	if !strings.Contains(input, "://") { input = "https://" + input }
	u, err := url.ParseRequestURI(input)
	return err == nil && u.Host != ""
}

Try / catch

u, err := parseURL(input)
if err != nil {
	var parseErr error
	if errors.As(err, &parseErr) {
		return fmt.Errorf("invalid access hostname %q: %w", input, err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling parseURL (directly or via ssh, getAppURLFromArgs, sshGen, or the anonymous arg parser) with input containing characters illegal in a URL — control characters, spaces, unescaped '%' sequences, malformed brackets like '[::1' — or an empty string.

Common situations: Passing hostnames with typos or trailing punctuation; pasting URLs with spaces or full-width characters from terminals/docs; unescaped '%' in passwords embedded in URLs; empty --url flags in scripts where a variable was unset.

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/aafab9ce04ad6415. Report an issue: GitHub.