cloudflare/cloudflared · error
failed to start forwarding server
Error message
failed to start forwarding server
What it means
StartForwarder wraps any error from net.Listen when trying to bind the local TCP forwarding address. It means cloudflared could not set up the local listener that proxies connections to the origin over the tunnel. The wrapped underlying error (e.g. 'address already in use' or 'permission denied') is the actual cause.
Source
Thrown at carrier/carrier.go:70
// Write will write to Stdout
func (c *StdinoutStream) Write(p []byte) (int, error) {
return os.Stdout.Write(p)
}
// Helper to allow deferring the response close with a check that the resp is not nil
func closeRespBody(resp *http.Response) {
if resp != nil {
_ = resp.Body.Close()
}
}
// StartForwarder will setup a listener on a specified address/port and then
// forward connections to the origin by calling `Serve()`.
func StartForwarder(conn Connection, address string, shutdownC <-chan struct{}, options *StartOptions) error {
listener, err := net.Listen("tcp", address)
if err != nil {
return errors.Wrap(err, "failed to start forwarding server")
}
return Serve(conn, listener, shutdownC, options)
}
// StartClient will copy the data from stdin/stdout over a WebSocket connection
// to the edge (originURL)
func StartClient(conn Connection, stream io.ReadWriter, options *StartOptions) error {
return conn.ServeStream(options, stream)
}
// Serve accepts incoming connections on the specified net.Listener.
// Each connection is handled in a new goroutine: its data is copied over a
// WebSocket connection to the edge (originURL).
// `Serve` always closes `listener`.
func Serve(remoteConn Connection, listener net.Listener, shutdownC <-chan struct{}, options *StartOptions) error {
defer listener.Close()
errChan := make(chan error)
View on GitHub (pinned to 2253eeeb25)
Solutions
- Check if another process is bound to the address/port (lsof -i :<port> or netstat) and stop it or pick a different port.
- If using a privileged port, run as root, grant CAP_NET_BIND_SERVICE, or use a port >= 1024.
- Verify the --url address format (host:port) and that the interface/IP exists on the machine.
- Ensure only one cloudflared instance (or forwarding server) uses this address at a time.
Example fix
// before StartForwarder(conn, "localhost:80", shutdownC, options) // after StartForwarder(conn, "localhost:8080", shutdownC, options)
Defensive patterns
Strategy: validation
Validate before calling
ln, err := net.Listen("tcp", address)
if err != nil {
return fmt.Errorf("address %s unavailable: %w", address, err)
}
ln.Close() // free it before handing to StartForwarder Try / catch
if err := carrier.StartForwarder(conn, addr, shutdownC, opts); err != nil {
var oe *net.OpError
if errors.As(err, &oe) && strings.Contains(oe.Error(), "address already in use") {
addr = "localhost:0" // retry with ephemeral port
}
} Prevention
- Pick high, unprivileged ports (>=1024) for forwarding addresses.
- Check port availability before starting the forwarder.
- Ensure only one cloudflared instance runs per address.
When it happens
Trigger: Calling StartForwarder with an address that is already bound, a privileged port (<1024) without root/CAP_NET_BIND_SERVICE, an invalid address string, or an address on an interface that does not exist.
Common situations: Running two cloudflared instances at once (the second fails to bind --url), firing up a second copy of a dev server on the same local port, using port 80/443 as non-root, or a misconfigured --url value with a typo in the host/IP.
Related errors
- failed to listen to default metrics address: %w
- failed to bind to address (%s): %w
- failed to build quick tunnel request
- failed to request quick Tunnel
- failed to read quick-tunnel response
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/18fc65e67a60aecc.
Report an issue: GitHub.