cloudflare/cloudflared · error

Error starting local service %s

Error message

Error starting local service %s

What it means

StartOrigins iterates every ingress rule and calls the rule service's start function. When any local service (http, https, socks5, hello world, bastion, etc.) fails to start, the underlying error is wrapped with the rule's service string. It means one of the configured local origins could not be brought up, and cloudflared aborts starting origins.

Source

Thrown at ingress/ingress.go:209

// IsEmpty checks if there are any ingress rules.
func (ing Ingress) IsEmpty() bool {
	return len(ing.Rules) == 0
}

// IsSingleRule checks if the user only specified a single ingress rule.
func (ing Ingress) IsSingleRule() bool {
	return len(ing.Rules) == 1
}

// StartOrigins will start any origin services managed by cloudflared, e.g. proxy servers or Hello World.
func (ing Ingress) StartOrigins(
	log *zerolog.Logger,
	shutdownC <-chan struct{},
) error {
	for _, rule := range ing.Rules {
		if err := rule.Service.start(log, shutdownC, rule.Config); err != nil {
			return errors.Wrapf(err, "Error starting local service %s", rule.Service)
		}
	}
	return nil
}

// CatchAll returns the catch-all rule (i.e. the last rule)
func (ing Ingress) CatchAll() *Rule {
	return &ing.Rules[len(ing.Rules)-1]
}

// Gets the default ingress rule that will be return 503 status
// code for all incoming requests.
func GetDefaultIngressRules(log *zerolog.Logger) []Rule {
	noRulesService := newDefaultStatusCode(log)
	return []Rule{
		{
			Service: &noRulesService,
		},

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Read the wrapped inner error to identify which rule's service failed to start.
  2. Check the 'service' value for the failing rule in your ingress config for typos and correct scheme syntax (http://, https://, unix:, unix+tls:, status:, hello_world, bastion, socks5).
  3. Verify any referenced unix socket paths or hostnames exist and are reachable.
  4. Run cloudflared with debug logging (--loglevel debug) to see the full startup stack.

Example fix

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

Strategy: validation

Validate before calling

for i, rule := range ing.Rules {
    if rule.Service == nil {
        return fmt.Errorf("rule #%d has no service", i+1)
    }
    switch {
    case strings.HasPrefix(string(*rule.Service), "http://"),
        strings.HasPrefix(string(*rule.Service), "https://"),
        strings.HasPrefix(string(*rule.Service), "unix:"),
        strings.HasPrefix(string(*rule.Service), "unix+tls:"),
        strings.HasPrefix(string(*rule.Service), "http_status:"),
        *rule.Service == "hello_world", *rule.Service == "bastion", *rule.Service == "socks5":
    default:
        return fmt.Errorf("rule #%d has unsupported service %q", i+1, *rule.Service)
    }
}

Try / catch

if err := ing.StartOrigins(log, shutdownC); err != nil {
    log.Error().Err(err).Msg("failed to start origins; check ingress service definitions")
    return err
}

Prevention

When it happens

Trigger: Calling Ingress.StartOrigins after a rule's Service.start returns an error, e.g. an http/https origin URL that fails to parse, a socks5 or bastion misconfiguration, or the embedded hello world server failing to listen.

Common situations: Typos in the ingress 'service' field in config.yml (e.g. 'http:/localhost:8080' with a missing slash), pointing at an invalid unix+tls path, or an origin service whose start prerequisites are missing.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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