cloudflare/cloudflared · error
%s doesn't have a hostname, consider adding a scheme
Error message
%s doesn't have a hostname, consider adding a scheme
What it means
After url.Parse succeeds, testURLCommand additionally requires the parsed URL to have a hostname or a scheme. A bare string like 'example.com' parses successfully but yields no hostname or scheme, so this error suggests adding a scheme. It guards against testing ingress rules against ambiguous host-only inputs.
Source
Thrown at cmd/cloudflared/tunnel/ingress_subcommands.go:131
return nil, errors.New("No configuration file was found. Please create one, or use the --config flag to specify its filepath. You can use the help command to learn more about configuration files")
}
fmt.Println("Validating rules from", conf.Source())
return conf, nil
}
// testURLCommand checks which ingress rule matches the given URL.
func testURLCommand(c *cli.Context) error {
requestArg := c.Args().First()
if requestArg == "" {
return errors.New("cloudflared tunnel rule expects a single argument, the URL to test")
}
requestURL, err := url.Parse(requestArg)
if err != nil {
return fmt.Errorf("%s is not a valid URL", requestArg)
}
if requestURL.Hostname() == "" && requestURL.Scheme == "" {
return fmt.Errorf("%s doesn't have a hostname, consider adding a scheme", requestArg)
}
conf := config.GetConfiguration()
fmt.Println("Using rules from", conf.Source())
ing, err := ingress.ParseIngress(conf)
if err != nil {
return errors.Wrap(err, "Validation failed")
}
_, i := ing.FindMatchingRule(requestURL.Hostname(), requestURL.Path)
fmt.Printf("Matched rule #%d\n", i)
fmt.Println(ing.Rules[i].MultiLineString())
return nil
}
View on GitHub (pinned to 2253eeeb25)
Solutions
- Prefix the argument with a scheme: `cloudflared tunnel ingress url https://example.com`
- Include the full origin URL you expect requests to match, e.g. `http://localhost:8080/path`
- If you only meant to test hostname matching, remember the command needs scheme+host to mirror a real request
Example fix
// before $ cloudflared tunnel ingress url example.com // after $ cloudflared tunnel ingress url https://example.com
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(arg)
if err == nil && u.Hostname() == "" && u.Scheme == "" {
arg = "https://" + arg // coerce host-only input
} Type guard
func hasHostOrScheme(s string) bool { u, err := url.Parse(s); return err == nil && (u.Hostname() != "" || u.Scheme != "") } Try / catch
if u.Hostname() == "" && u.Scheme == "" {
return fmt.Errorf("add a scheme to %q, e.g. https://%s", arg, arg)
} Prevention
- Habitually include https:// when referencing origins in cloudflared commands and configs
- Prefer absolute http://localhost:PORT URLs when testing local ingress rules
- Share full-URL examples in runbooks, not bare hostnames
When it happens
Trigger: Running `cloudflared tunnel ingress url example.com` — url.Parse succeeds but Hostname() == "" and Scheme == "".
Common situations: Testing a ingress hostname rule without a scheme prefix; forgetting http:// or https:// when copy-pasting domains; documenting examples that use bare hostnames.
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/e13edf79420e165b.
Report an issue: GitHub.