caddyserver/caddy · error

listen on 127.0.0.1:0: %v; listen on [::1]:0: %v

Error message

listen on 127.0.0.1:0: %v; listen on [::1]:0: %v

What it means

The aggregated error from listenTCPForPingback when both loopback binds fail: first tcp4 on 127.0.0.1:0, then tcp6 on [::1]:0. The message chains both underlying errors. Since port 0 is used (kernel-assigned), conflicts are impossible — failure means listen sockets themselves are unavailable (FD limits, disabled loopback, sandbox policy).

Source

Thrown at cmd/commandfuncs.go:185

	}

	return caddy.ExitCodeSuccess, nil
}

type tcpListenFunc func(network, address string) (net.Listener, error)

func listenTCPForPingback(listen tcpListenFunc) (net.Listener, error) {
	ln, ipv4Err := listen("tcp4", "127.0.0.1:0")
	if ipv4Err == nil {
		return ln, nil
	}

	ln, ipv6Err := listen("tcp6", "[::1]:0")
	if ipv6Err == nil {
		return ln, nil
	}

	return nil, fmt.Errorf("listen on 127.0.0.1:0: %v; listen on [::1]:0: %v", ipv4Err, ipv6Err)
}

func cmdRun(fl Flags) (int, error) {
	caddy.TrapSignals()

	// set up buffered logging for early startup
	// so that we can hold onto logs until after
	// the config is loaded (or fails to load)
	// so that we can write the logs to the user's
	// configured output. we must be sure to flush
	// on any error before the config is loaded.
	logger, defaultLogger, logBuffer := caddy.BufferedLog()

	undoMaxProcs := setResourceLimits(logger)
	defer undoMaxProcs()
	// release the local reference to the undo function so it can be GC'd;
	// the deferred call above has already captured the actual function value.
	undoMaxProcs = nil //nolint:ineffassign,wastedassign

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Raise FD limits (ulimit -n 4096) and retry
  2. Confirm loopback exists: ip addr show lo
  3. In containers, use a normal network stack (not --network none)
  4. Fall back to `caddy run` for foreground operation without the pingback handshake

Example fix

# before
caddy start  # listen on 127.0.0.1:0: ...; listen on [::1]:0: ...
# after
ulimit -n 4096 && caddy start
Defensive patterns

Strategy: fallback

Validate before calling

// pre-flight: both loopback families
for _, addr := range []string{"127.0.0.1:0", "[::1]:0"} {
    if ln, err := net.Listen("tcp", addr); err == nil { ln.Close(); return nil }
}
return errors.New("loopback listen unavailable — fix networking/ulimit or use `caddy run`")

Prevention

When it happens

Trigger: FD exhaustion (EMFILE) when both binds are attempted; loopback interface down or missing (some minimal containers or network namespaces); security policy (SELinux, seccomp) denying bind; macOS firewall blocking loopback listens in rare configurations.

Common situations: CI containers with harsh ulimits; --network none containers stripped of loopback; hardened hosts denying unprivileged listen sockets.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/f71c615fd9e8fe38. Report an issue: GitHub.