cloudflare/cloudflared · error

URL has invalid format

Error message

URL %s has invalid format

What it means

After percent-decoding, validateUrlString parses the URL with url.Parse. If parsing fails (structurally malformed URL that Go's parser rejects), this error is returned. It is only reached for non-IP inputs whose percent-escapes were valid.

Solutions

  1. Trim whitespace and remove control characters from the URL before passing it in
  2. Verify the URL parses with a quick check: u, err := url.Parse(strings.TrimSpace(origin))
  3. Fix the URL in your config/flag; quotes or spaces around the value are common culprits
  4. If passing a hostname only, ensure it contains no spaces or special characters

Example fix

// before
origin := "http://example.com /path"
ValidateUrl(origin) // invalid format
// after
origin := strings.TrimSpace("http://example.com /path")
origin = strings.ReplaceAll(origin, " ", "%20")
ValidateUrl(origin)
Defensive patterns

Strategy: validation

Validate before calling

func parseableURL(s string) bool {
    _, err := url.Parse(strings.TrimSpace(s))
    return err == nil
}

Try / catch

u, err := validation.ValidateUrl(origin)
if err != nil {
    return fmt.Errorf("config: bad origin_url %q: %w", origin, err)
}

Prevention

When it happens

Trigger: ValidateUrl or NewAccessValidator called with a string url.Parse rejects, e.g. 'http://exa mple.com' (raw space in host), or an ASCII control character embedded in the URL.

Common situations: Whitespace accidentally included in config values (trailing spaces/newlines pasted from terminals), control characters from env vars, or corrupted config file content.

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

Appendix: source

Thrown at validation/validation.go:105

	} else if strings.HasPrefix(originUrl, "[") && strings.HasSuffix(originUrl, "]") {
		// ParseIP doesn't recoginze [::1]
		return validateIP("", originUrl[1:len(originUrl)-1], "")
	}

	host, port, err := net.SplitHostPort(originUrl)
	// user might pass in an ip address like 127.0.0.1
	if err == nil && net.ParseIP(host) != nil {
		return validateIP("", host, port)
	}

	unescapedUrl, err := url.PathUnescape(originUrl)
	if err != nil {
		return "", fmt.Errorf("URL %s has invalid escape characters %s", originUrl, unescapedUrl)
	}

	parsedUrl, err := url.Parse(unescapedUrl)
	if err != nil {
		return "", fmt.Errorf("URL %s has invalid format", originUrl)
	}

	// if the url is in the form of host:port, IsAbs() will think host is the schema
	var hostname string
	hasScheme := parsedUrl.IsAbs() && parsedUrl.Host != ""
	if hasScheme {
		err := validateScheme(parsedUrl.Scheme)
		if err != nil {
			return "", err
		}
		// The earlier check for ip address will miss the case http://[::1]
		// and http://[::1]:8080
		if net.ParseIP(parsedUrl.Hostname()) != nil {
			return validateIP(parsedUrl.Scheme, parsedUrl.Hostname(), parsedUrl.Port())
		}
		hostname, err = ValidateHostname(parsedUrl.Hostname())
		if err != nil {
			return "", fmt.Errorf("URL %s has invalid format", originUrl)

View on GitHub (pinned to 2253eeeb25)