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

  1. Wait for the tunnel to finish connecting, then retry `cloudflared tunnel ready` (add retry/backoff in health-check scripts).
  2. Check tunnel logs (`cloudflared tunnel run` output) for edge connection failures if 503 persists.
  3. 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

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


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