cloudflare/cloudflared · error

%s is an invalid address, please make sure it has a scheme a

Error message

%s is an invalid address, please make sure it has a scheme and a hostname

What it means

For non-special service values, validateIngress parses the Service string as a URL and requires both a scheme and a hostname. If either is missing, the address cannot be dialed as an origin, so this error names the offending value and explains the requirement.

Source

Thrown at ingress/ingress.go:301

				return Ingress{}, fmt.Errorf("unable to create ip access policy for %s: %s", r.Service, err)
			}

			service = newSocksProxyOverWSService(accessPolicy)
		} else if r.Service == ServiceBastion || cfg.BastionMode {
			// Bastion mode will always start a Websocket proxy server, which will
			// overwrite the localService.URL field when `start` is called. So,
			// leave the URL field empty for now.
			cfg.BastionMode = true
			service = newBastionService()
		} else {
			// Validate URL services
			u, err := url.Parse(r.Service)
			if err != nil {
				return Ingress{}, err
			}

			if u.Scheme == "" || u.Hostname() == "" {
				return Ingress{}, fmt.Errorf("%s is an invalid address, please make sure it has a scheme and a hostname", r.Service)
			}

			if u.Path != "" {
				return Ingress{}, fmt.Errorf("%s is an invalid address, ingress rules don't support proxying to a different path on the origin service. The path will be the same as the eyeball request's path", r.Service)
			}
			if isHTTPService(u) {
				service = &httpService{url: u}
			} else {
				service = newTCPOverWSService(u)
			}
		}

		var handlers []middleware.Handler
		if access := r.OriginRequest.Access; access != nil {
			if err := validateAccessConfiguration(access); err != nil {
				return Ingress{}, err
			}
			if access.Required {

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Add a scheme to the service URL, e.g. `http://localhost:8080` or `https://backend.internal`
  2. Ensure the hostname is present after the scheme (not just `http://`)
  3. Check for YAML quoting issues that strip part of the URL

Example fix

// before
service: localhost:8080
// after
service: http://localhost:8080
Defensive patterns

Strategy: validation

Validate before calling

func validOriginService(svc string) error {
	u, err := url.Parse(svc)
	if err != nil { return err }
	if u.Scheme == "" || u.Hostname() == "" {
		return fmt.Errorf("service %q needs scheme and hostname", svc)
	}
	return nil
}

Try / catch

if err := ingress.ParseIngress(cfg); err != nil {
	if strings.Contains(err.Error(), "is an invalid address") {
		// fix the service URL to include scheme://host
	}
	return err
}

Prevention

When it happens

Trigger: ParseIngress/UnmarshalJSON with a service value like `localhost:8080` (no scheme), `http://` (no host), or `backend.internal` (no scheme), producing a parsed URL with empty Scheme or empty Hostname().

Common situations: Config entries such as `service: http://localhost:8080` accidentally missing the scheme (`localhost:8080`), or bare hostnames like `service: web-backend` instead of `service: http://web-backend:80`.

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