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
- Check the wrapped cause (%w) for the exact parse failure — usually an invalid character or escape sequence.
- Pass a plain hostname or a properly percent-encoded URL; avoid spaces and raw special characters.
- Ensure the variable supplying the URL is set and non-empty in scripts (`"${URL:?URL not set}"`).
- Use url.PathEscape/url.QueryEscape for dynamic components before composing the input string.
- 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
- Pass bare hostnames or fully formed https:// URLs without spaces
- Percent-encode dynamic URL components
- Fail fast in scripts when the URL variable is empty/unset
- Prefer bracketed IPv6 literals [::1] over raw forms
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- not a valid host
- no input provided
- invalid connection override: %s
- error validating origin URL
- not a valid url
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/aafab9ce04ad6415.
Report an issue: GitHub.