caddyserver/caddy · error
opening listener for success confirmation: %v
Error message
opening listener for success confirmation: %v
What it means
Returned by `caddy start` when it cannot open the loopback TCP listener used to receive the child process's success pingback. Before spawning the detached child, the parent binds 127.0.0.1:0 (or [::1]:0 as fallback); failure means the OS refused a loopback listen — socket exhaustion, loopback disabled, or socket limits (ulimit).
Source
Thrown at cmd/commandfuncs.go:64
configFlag := fl.String("config")
configAdapterFlag := fl.String("adapter")
pidfileFlag := fl.String("pidfile")
watchFlag := fl.Bool("watch")
var err error
var envfileFlag []string
envfileFlag, err = fl.GetStringSlice("envfile")
if err != nil {
return caddy.ExitCodeFailedStartup,
fmt.Errorf("reading envfile flag: %v", err)
}
// open a listener to which the child process will connect when
// it is ready to confirm that it has successfully started
ln, err := listenTCPForPingback(net.Listen)
if err != nil {
return caddy.ExitCodeFailedStartup,
fmt.Errorf("opening listener for success confirmation: %v", err)
}
defer ln.Close()
// craft the command with a pingback address and with a
// pipe for its stdin, so we can tell it our confirmation
// code that we expect so that some random port scan at
// the most unfortunate time won't fool us into thinking
// the child succeeded (i.e. the alternative is to just
// wait for any connection on our listener, but better to
// ensure it's the process we're expecting - we can be
// sure by giving it some random bytes and having it echo
// them back to us)
cmd := exec.Command(os.Args[0], "run", "--pingback", ln.Addr().String()) //nolint:gosec // no command injection that I can determine...
// we should be able to run caddy in relative paths
if errors.Is(cmd.Err, exec.ErrDot) {
cmd.Err = nil
}
if configFlag != "" {View on GitHub (pinned to 50e54ee279)
Solutions
- Raise the file-descriptor limit: ulimit -n 4096 (or higher), then retry caddy start
- Verify loopback works: curl http://127.0.0.1:1/ or ss -ltn should not error
- In containers, ensure networking is not disabled (avoid --network none for caddy start)
- As a workaround use `caddy run` (foreground), which needs no pingback listener
Example fix
# before caddy start # opening listener for success confirmation: ... address already in use / too many open files # after ulimit -n 4096 && caddy start
Defensive patterns
Strategy: fallback
Validate before calling
// pre-flight: can we bind loopback at all?
ln, err := net.Listen("tcp4", "127.0.0.1:0")
if err != nil {
return fmt.Errorf("loopback bind failed (%v) — raise ulimit -n or fix networking; use `caddy run` instead", err)
}
ln.Close() Prevention
- Set adequate ulimit -n in service units (LimitNOFILE=4096+)
- Avoid `caddy start` in containers without loopback networking; use `caddy run` under the container init
When it happens
Trigger: Running `caddy start` with file-descriptor limits exhausted (thousands of open sockets); a container with networking disabled or a broken loopback interface; SELinux/AppArmor denying socket() to the process; extremely rare kernel-level resource shortage.
Common situations: Heavily loaded hosts or CI runners out of FDs; minimal containers (network=none) where loopback TCP bind fails; security policies restricting listen sockets.
Related errors
- listen on 127.0.0.1:0: %v; listen on [::1]:0: %v
- creating stdin pipe: %v
- dialing confirmation address: %v
- reading envfile flag: %v
- generating random confirmation bytes: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/1132547371f91c98.
Report an issue: GitHub.