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

  1. Read the wrapped inner error; it names the offending rule/line in the config.
  2. Fix the ingress rule syntax: each rule needs hostname + service, with the catch-all '- service: http_status:404' last.
  3. Remove the --url flag when using ingress rules (they are mutually exclusive).
  4. 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

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


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/2ad84c0754684826. Report an issue: GitHub.