cloudflare/cloudflared · error

failed to bind to address (%s): %w

Error message

failed to bind to address (%s): %w

What it means

Returned when cloudflared is given an explicit metrics listen address and listeners.Listen("tcp", laddr) fails to bind it. The configured address is included in the message and the underlying net.OpError is wrapped. This is the explicit-address counterpart of the default-address bind failure.

Source

Thrown at metrics/metrics.go:137

			listener, err := listeners.Listen("tcp", address)
			if err == nil {
				return listener, nil
			}
		}

		// When no port is available then bind to a random one
		listener, err := listeners.Listen("tcp", laddr)
		if err != nil {
			return nil, fmt.Errorf("failed to listen to default metrics address: %w", err)
		}

		return listener, nil
	}

	// Explicitly got a local address then bind to it
	listener, err := listeners.Listen("tcp", laddr)
	if err != nil {
		return nil, fmt.Errorf("failed to bind to address (%s): %w", laddr, err)
	}

	return listener, nil
}

func ServeMetrics(
	l net.Listener,
	ctx context.Context,
	config Config,
	log *zerolog.Logger,
) (err error) {
	var wg sync.WaitGroup
	// Metrics port is privileged, so no need for further access control
	trace.AuthRequest = func(*http.Request) (bool, bool) { return true, true }
	h := newMetricsHandler(config, log)
	server := &http.Server{
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 10 * time.Second,

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Inspect the wrapped cause: 'address already in use' → free the port; 'cannot assign requested address' → fix the IP/host
  2. Choose a free port and update --metrics (e.g. --metrics 127.0.0.1:33755)
  3. Bind to 0.0.0.0 or localhost instead of a stale interface IP
  4. Verify /etc/hosts or DNS resolves the hostname in the metrics address

Example fix

// before
cloudflared tunnel run --metrics 127.0.0.1:20241  # already in use
// after
cloudflared tunnel run --metrics 127.0.0.1:20242  # verified free with ss -ltnp
Defensive patterns

Strategy: validation

Validate before calling

func metricsAddrBindable(addr string) error {
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        return fmt.Errorf("metrics address %s not bindable: %w", addr, err)
    }
    return ln.Close()
}
// run before launching cloudflared with --metrics <addr>

Prevention

When it happens

Trigger: Calling ServeMetrics / StartMetricsServer with an explicit --metrics address that is already bound by another process, is malformed, resolves to an address not present on the host, or requires privileges (ports <1024).

Common situations: --metrics pointing at a port another daemon already uses; binding to a specific interface IP that no longer exists (DHCP change); typo in host causing resolver failure; running in a container without the IP; two services configured with the same metrics port in deployment manifests.

Related errors


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