cloudflare/cloudflared · error

invalid HTTP status code

Error message

invalid HTTP status code

What it means

Ingress rules can use a 'http_status:CODE' service to return a fixed HTTP status. This error is wrapped when the text after 'http_status:' cannot be parsed as an integer by strconv.Atoi. The ingress config is rejected entirely and ParseIngress returns an Ingress{} zero value with this error.

Source

Thrown at ingress/ingress.go:261

}

func validateIngress(ingress []config.UnvalidatedIngressRule, defaults OriginRequestConfig) (Ingress, error) {
	rules := make([]Rule, len(ingress))
	for i, r := range ingress {
		cfg := setConfig(defaults, r.OriginRequest)
		var service OriginService

		if prefix := "unix:"; strings.HasPrefix(r.Service, prefix) {
			// No validation necessary for unix socket filepath services
			path := strings.TrimPrefix(r.Service, prefix)
			service = &unixSocketPath{path: path, scheme: "http"}
		} else if prefix := "unix+tls:"; strings.HasPrefix(r.Service, prefix) {
			path := strings.TrimPrefix(r.Service, prefix)
			service = &unixSocketPath{path: path, scheme: "https"}
		} else if prefix := "http_status:"; strings.HasPrefix(r.Service, prefix) {
			statusCode, err := strconv.Atoi(strings.TrimPrefix(r.Service, prefix))
			if err != nil {
				return Ingress{}, errors.Wrap(err, "invalid HTTP status code")
			}
			if statusCode < 100 || statusCode > 999 {
				return Ingress{}, fmt.Errorf("invalid HTTP status code: %d", statusCode)
			}
			srv := newStatusCode(statusCode)
			service = &srv
		} else if r.Service == HelloWorldFlag || r.Service == HelloWorldService {
			service = new(helloWorld)
		} else if r.Service == ServiceSocksProxy {
			rules := make([]ipaccess.Rule, len(r.OriginRequest.IPRules))

			for i, ipRule := range r.OriginRequest.IPRules {
				rule, err := ipaccess.NewRuleByCIDR(ipRule.Prefix, ipRule.Ports, ipRule.Allow)
				if err != nil {
					return Ingress{}, fmt.Errorf("unable to create ip rule for %s: %s", r.Service, err)
				}
				rules[i] = rule
			}

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Make the service value exactly 'http_status:<integer>', e.g. http_status:404 with no extra text.
  2. Quote the YAML value if it may be misinterpreted: service: "http_status:404".
  3. Note a separate check requires 100 <= code <= 999; pick a code in that range to avoid the sibling error.

Example fix

// before
service: http_status: Not Found
// after
service: http_status:404
Defensive patterns

Strategy: validation

Validate before calling

func validHTTPStatusService(svc string) error {
    const prefix = "http_status:"
    if !strings.HasPrefix(svc, prefix) {
        return nil
    }
    code, err := strconv.Atoi(strings.TrimPrefix(svc, prefix))
    if err != nil {
        return fmt.Errorf("http_status must be an integer, got %q", svc)
    }
    if code < 100 || code > 999 {
        return fmt.Errorf("http_status code %d out of range 100-999", code)
    }
    return nil
}

Try / catch

ing, err := ingress.ParseIngress(conf)
if err != nil {
    return fmt.Errorf("invalid ingress config: %w", err)
}

Prevention

When it happens

Trigger: An ingress rule with service like 'http_status: twohundred', 'http_status: 200 OK', 'http_status:' (empty), or any non-numeric suffix so strconv.Atoi fails.

Common situations: Hand-edited config.yml with a typo or stray text in the status code, YAML quoting mistakes, or copy-pasting 'http_status:404 ' with trailing characters.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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