cloudflare/cloudflared · error

URL no %s has invalid format

Error message

URL no %s has invalid format

What it means

In the no-scheme branch, when net.SplitHostPort left host empty (input had no scheme and wasn't host:port-IP), the whole originUrl is validated as a hostname. If ValidateHostname fails, this error (note the odd 'URL no %s' wording, a typo for the URL without scheme) is returned.

Source

Thrown at validation/validation.go:133

		}
		// 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)
		}
		if parsedUrl.Port() != "" {
			return fmt.Sprintf("%s://%s", parsedUrl.Scheme, net.JoinHostPort(hostname, parsedUrl.Port())), nil
		}
		return fmt.Sprintf("%s://%s", parsedUrl.Scheme, hostname), nil
	} else {
		if host == "" {
			hostname, err = ValidateHostname(originUrl)
			if err != nil {
				return "", fmt.Errorf("URL no %s has invalid format", originUrl)
			}
			return fmt.Sprintf("%s://%s", defaultScheme, hostname), nil
		} else {
			hostname, err = ValidateHostname(host)
			if err != nil {
				return "", fmt.Errorf("URL %s has invalid format", originUrl)
			}
			// This is why the path is preserved when `originUrl` doesn't have a schema.
			// Using `parsedUrl.Port()` here, instead of `port`, would remove the path
			return fmt.Sprintf("%s://%s", defaultScheme, net.JoinHostPort(hostname, port)), nil
		}
	}

}

func validateScheme(scheme string) error {
	for _, protocol := range supportedProtocols {
		if scheme == protocol {

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Check the scheme-less value is a valid hostname (letters, digits, hyphens, dots) or host:port
  2. Add an explicit scheme (http:// or ssh://) so the URL branch is taken instead of the hostname branch
  3. Run idna.ToASCII on the value directly to see the real validation failure hidden by this wrapper
  4. Fix typos or invalid characters in the config value

Example fix

// before
ValidateUrl("my_host:abc") // URL no my_host:abc has invalid format
// after
ValidateUrl("tcp://my_host:2000") // explicit supported scheme
Defensive patterns

Strategy: validation

Validate before calling

func validOrigin(s string) bool {
    if strings.Contains(s, ":") { return true } // has scheme or port
    _, err := idna.ToASCII(s)
    return err == nil && s != ""
}

Try / catch

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

Prevention

When it happens

Trigger: ValidateUrl('bad_host!') or any scheme-less input whose hostname fails ValidateHostname: invalid IDNA characters, strings containing ':' that don't unescape/parse (e.g. 'localhost:port' with a non-numeric port reaching the hostname path).

Common situations: Typo'd hostnames in ingress config, scheme-less values like 'my_service:2000' where SplitHostPort succeeded (host='my_service' actually — this branch hits when host==''), or unicode hostnames in config files.

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