cloudflare/cloudflared · error
Validation failed
Error message
Validation failed
What it means
`cloudflared tunnel ingress validate` parses the ingress rules from the config file plus CLI flags via ingress.ParseIngress. Any rule error (bad URL, malformed service, invalid rule fields) is wrapped as 'Validation failed'. The command also rejects combining --url with ingress rules.
Source
Thrown at cmd/cloudflared/tunnel/ingress_subcommands.go:89
UsageText: "cloudflared tunnel [--config FILEPATH] ingress rule URL",
ArgsUsage: "URL",
Description: "Check which ingress rule matches a given request URL. " +
"Ingress rules match a request's hostname and path. Hostname is " +
"optional and is either a full hostname like `www.example.com` or a " +
"hostname with a `*` for its subdomains, e.g. `*.example.com`. Path " +
"is optional and matches a regular expression, like `/[a-zA-Z0-9_]+.html`",
}
}
// validateIngressCommand check the syntax of the ingress rules in the cloudflared config file
func validateIngressCommand(c *cli.Context, warnings string) error {
conf, err := getConfiguration(c)
if err != nil {
return err
}
if _, err := ingress.ParseIngress(conf); err != nil {
return errors.Wrap(err, "Validation failed")
}
if c.IsSet("url") {
return ingress.ErrURLIncompatibleWithIngress
}
if warnings != "" {
fmt.Println("Warning: unused keys detected in your config file. Here is a list of unused keys:")
fmt.Println(warnings)
return nil
}
fmt.Println("OK")
return nil
}
func getConfiguration(c *cli.Context) (*config.Configuration, error) {
var conf *config.Configuration
if c.IsSet(ingressDataJSONFlagName) {
ingressJSON := c.String(ingressDataJSONFlagName)
fmt.Println("Validating rules from cmdline flag --json")View on GitHub (pinned to 2253eeeb25)
Solutions
- Read the wrapped inner error; it names the offending rule/line in the config.
- Fix the ingress rule syntax: each rule needs hostname + service, with the catch-all '- service: http_status:404' last.
- Remove the --url flag when using ingress rules (they are mutually exclusive).
- Validate the YAML structure/indentation of the ingress section.
Example fix
// before (config.yml)
ingress:
- hostname: app.example.com
// missing service and catch-all
// after
ingress:
- hostname: app.example.com
service: http://localhost:8080
- service: http_status:404 Defensive patterns
Strategy: validation
Validate before calling
// sanity-check ingress config before validating
def checkIngress(cfg map[string]interface{}) error {
ingress, ok := cfg["ingress"].([]interface{})
if !ok || len(ingress) == 0 { return errors.New("no ingress rules") }
last, _ := ingress[len(ingress)-1].(map[string]interface{})
if _, ok := last["service"]; !ok { return errors.New("missing catch-all rule") }
return nil
} Try / catch
if _, err := ingress.ParseIngress(conf); err != nil {
return errors.Wrap(err, "Validation failed")
} Prevention
- End every ingress list with the catch-all `- service: http_status:404`
- Never combine --url with an ingress block
- Run `cloudflared tunnel ingress validate` after every config edit
- Use consistent YAML indentation (2 spaces) in config.yml
When it happens
Trigger: Running `cloudflared tunnel ingress validate` with a config file whose ingress section contains a malformed rule, or passing --url together with ingress rules in the config.
Common situations: YAML ingress entries missing 'service', invalid hostname patterns, unreachable service URLs like typo'd schemes, mixing --url flag with an ingress block, indentation mistakes in the config.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- %s is not a valid URL
- %s doesn't have a hostname, consider adding a scheme
- not a valid host
- no input provided
- failed to parse Host
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/2ad84c0754684826.
Report an issue: GitHub.