cloudflare/cloudflared · error
http://%s/ready endpoint returned status code %d %s
Error message
http://%s/ready endpoint returned status code %d %s
What it means
readyCommand probes a running cloudflared instance's metrics/ready endpoint (http://<metrics-host>/ready) and expects HTTP 200. Any other status code (e.g. 503 when no connections are established yet) is converted into this error including the response body, since it means the instance is not healthy.
Source
Thrown at cmd/cloudflared/tunnel/subcommands.go:503
}
requestURL := fmt.Sprintf("http://%s/ready", metricsOpts)
req, err := http.NewRequest(http.MethodGet, requestURL, nil)
if err != nil {
return err
}
// nolint: gosec // URL is constructed from the user-configured local metrics endpoint.
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer func() { _ = res.Body.Close() }()
if res.StatusCode != 200 {
body, err := io.ReadAll(res.Body)
if err != nil {
return err
}
return fmt.Errorf("http://%s/ready endpoint returned status code %d\n%s", metricsOpts, res.StatusCode, body)
}
return nil
}
func buildInfoCommand() *cli.Command {
return &cli.Command{
Name: "info",
Action: cliutil.ConfiguredAction(tunnelInfo),
Usage: "List details about the active connectors for a tunnel",
UsageText: "cloudflared tunnel [tunnel command options] info [subcommand options] [TUNNEL]",
Description: "cloudflared tunnel info displays details about the active connectors for a given tunnel (identified by name or uuid).",
Flags: []cli.Flag{
outputFormatFlag,
showRecentlyDisconnected,
sortInfoByFlag,
invertInfoSortFlag,
},
CustomHelpTemplate: commandHelpTemplate(),View on GitHub (pinned to 2253eeeb25)
Solutions
- Wait for the tunnel to finish connecting, then retry `cloudflared tunnel ready` (add retry/backoff in health-check scripts).
- Check tunnel logs (`cloudflared tunnel run` output) for edge connection failures if 503 persists.
- Verify the --metrics address matches the one the running instance was started with.
Example fix
// before cloudflared tunnel ready --url http://localhost:20241 // after for i in $(seq 1 30); do cloudflared tunnel ready --url http://localhost:20241 && break sleep 2 done
Defensive patterns
Strategy: retry
Validate before calling
resp, err := http.Get("http://localhost:20241/ready")
if err == nil && resp.StatusCode != http.StatusOK {
// not ready yet — wait before running the ready command
time.Sleep(2 * time.Second)
} Try / catch
// backoff loop around the ready probe
for i := 0; i < 15; i++ {
if err := readyCheck(); err == nil { return nil }
time.Sleep(2 * time.Second)
}
return fmt.Errorf("tunnel never became ready: %w", err) Prevention
- Only probe /ready after the tunnel process has had time to establish edge connections.
- Verify the --metrics address matches the running instance.
- Add retry/backoff to health-check scripts instead of failing on first non-200.
When it happens
Trigger: Running `cloudflared tunnel ready` against an instance whose /ready endpoint returns non-200 — typically a tunnel that has not yet established its edge connections, or whose metrics address is wrong and is answered by a different server.
Common situations: Health-check scripts racing tunnel startup (ready before connections complete); pointing at a host where another service returns 404; the running cloudflared lost its edge connections and reports 503.
Related errors
- --metrics has to be provided
- unable to check for update: %d
- failed to request quick Tunnel
- the argument path must be a directory
- No GPG keys were provided for signing
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/edb520475d2f80f1.
Report an issue: GitHub.