cloudflare/cloudflared · error
unrecognized service: %s, %t
Error message
unrecognized service: %s, %t
What it means
Returned by Proxy.ProxyHTTP when the resolved ingress rule's service type does not match any service kind the proxy knows how to handle (httpstatuses, bastion, HTTPLocalProxy, etc.). It means the ingress rule's Service field parsed into a type ProxyHTTP cannot dispatch, and the error includes both the service string and whether an origin proxy was produced. This indicates a misconfiguration or an unhandled service type in the ingress rules.
Source
Thrown at proxy/proxy.go:139
if err != nil {
return err
}
flusher, ok := w.(http.Flusher)
if !ok {
return fmt.Errorf("response writer is not a flusher")
}
rws := connection.NewHTTPResponseReadWriterAcker(w, flusher, req)
logger := logger.With().Str(logFieldDestAddr, dest).Logger()
if err := p.proxyStream(tr.ToTracedContext(), rws, dest, originProxy, &logger); err != nil {
logRequestError(&logger, err)
return err
}
return nil
case ingress.HTTPLocalProxy:
p.proxyLocalRequest(originProxy, w, req, isWebsocket)
return nil
default:
return fmt.Errorf("unrecognized service: %s, %t", rule.Service, originProxy)
}
}
// ProxyTCP proxies to a TCP connection between the origin service and cloudflared.
func (p *Proxy) ProxyTCP(
ctx context.Context,
conn connection.ReadWriteAcker,
req *connection.TCPRequest,
) error {
incrementTCPRequests()
defer decrementTCPConcurrentRequests()
logger := newTCPLogger(p.log, req)
// Try to start a new flow
if err := p.flowLimiter.Acquire(management.TCP.String()); err != nil {
logger.Warn().Msg("Too many concurrent flows being handled, rejecting tcp proxy")
return errors.Wrap(err, "failed to start tcp flow due to rate limiting")View on GitHub (pinned to 2253eeeb25)
Solutions
- Check the rule's service value in the error output and correct the scheme (http://, https://, http_status:, bastion, unix:, etc.)
- Validate the full config before running: cloudflared tunnel ingress validate
- Upgrade cloudflared if the service type comes from remote config newer than the binary
- For tests, construct rules only via ingress.ParseIngress so invalid service types are rejected early
Example fix
// before (config.yml) ingress: - service: htp://localhost:8080 // after ingress: - service: http://localhost:8080
Defensive patterns
Strategy: validation
Validate before calling
// Validate ingress rules before running the tunnel
// shell: cloudflared tunnel ingress validate
// Go: parse rules through the supported parser
rules, err := ingress.ParseIngress(rawConfig)
if err != nil {
return fmt.Errorf("invalid ingress service: %w", err)
}
for _, r := range rules.Rules {
if !supportedServiceSchemes[strings.SplitN(r.Service, ":", 2)[0]] {
return fmt.Errorf("unsupported service: %s", r.Service)
}
} Try / catch
err := proxy.ProxyHTTP(ctx, w, r, rule, log)
if err != nil && strings.Contains(err.Error(), "unrecognized service") {
log.Error().Str("service", rule.Service.String()).Msg("ingress rule service type not supported; check scheme and cloudflared version")
http.Error(w, "misconfigured service", http.StatusBadGateway)
return
} Prevention
- Run `cloudflared tunnel ingress validate` before deploying config changes
- Only use documented service schemes: http://, https://, http_status:, bastion, unix:, unix+tls:, ws://
- Keep the binary version in sync with remote configuration that may introduce newer service types
When it happens
Trigger: An ingress rule's service URL has a scheme cloudflared does not recognize or cannot resolve to an origin service (e.g. unsupported scheme, malformed service string that still parsed), so the type switch in ProxyHTTP falls into the default branch.
Common situations: Typos in the service scheme in config.yml (e.g. 'htp://' instead of 'http://', missing 'http_status:'); remote-config pushing a service type newer than the running cloudflared binary supports; tests exercising ProxyHTTP with a rule whose service was never validated by ingress parsing.
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
- Hostname patterns can have at most one wildcard character ("
- Hostname cannot contain a port
- ErrURLIncompatibleWithIngress
- access.TeamName cannot be blank when access.audTags are pres
- unable to generate a connector UUID: %w
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/025dfe734d351711.
Report an issue: GitHub.