caddyserver/caddy · error
reading confirmation bytes from stdin: %v
Error message
reading confirmation bytes from stdin: %v
What it means
Returned by `caddy run --pingback` (the child of `caddy start`) when io.ReadAll(os.Stdin) fails while reading the confirmation bytes the parent wrote to the pipe. Failure means the stdin pipe was in a bad state — the parent died before/while writing, or stdin was closed/replaced by an incompatible descriptor.
Source
Thrown at cmd/commandfuncs.go:306
// release the reference to the config so it can be GC'd
config = nil //nolint:ineffassign,wastedassign
// at this stage the config will have replaced the
// default logger to the configured one, so we can
// log normally, now that the config is running.
// also clear our ref to the buffer so it can get GC'd
logger = caddy.Log()
defaultLogger = nil //nolint:ineffassign,wastedassign
logBuffer = nil //nolint:wastedassign,ineffassign
logger.Info("serving initial configuration")
// if we are to report to another process the successful start
// of the server, do so now by echoing back contents of stdin
if pingbackFlag != "" {
confirmationBytes, err := io.ReadAll(os.Stdin)
if err != nil {
return caddy.ExitCodeFailedStartup,
fmt.Errorf("reading confirmation bytes from stdin: %v", err)
}
conn, err := net.Dial("tcp", pingbackFlag)
if err != nil {
return caddy.ExitCodeFailedStartup,
fmt.Errorf("dialing confirmation address: %v", err)
}
_, err = conn.Write(confirmationBytes)
if err != nil {
return caddy.ExitCodeFailedStartup,
fmt.Errorf("writing confirmation bytes to %s: %v", pingbackFlag, err)
}
// close (non-defer because we `select {}` below)
// and release references so they can be GC'd
conn.Close()
confirmationBytes = nil //nolint:ineffassign,wastedassign
conn = nil //nolint:wastedassign,ineffassign
}
View on GitHub (pinned to 50e54ee279)
Solutions
- Do not invoke `caddy run --pingback` manually — it is reserved for the caddy start handshake
- If seen during caddy start, check whether a supervisor/OOM killer terminated the parent; free memory and retry
- Use `caddy run` directly for foreground operation
Defensive patterns
Strategy: try-catch
Try / catch
// internal handshake flag: if you must run it, keep stdin open // err from caddy run --pingback containing 'reading confirmation bytes from stdin' // => parent pipe broken: ensure the parent (caddy start) stays alive or drop --pingback
Prevention
- Never use the --pingback flag manually; it belongs to the caddy start handshake
- Protect the parent process from OOM/signal races (memory limits, no aggressive kill timeouts)
When it happens
Trigger: The parent `caddy start` process is killed between spawning the child and writing the 32 bytes; running `caddy run --pingback addr` manually without a parent providing stdin; stdin redirected to a directory or a closed FD.
Common situations: Almost exclusively internal to the caddy start/run handshake; manual use of the undocumented --pingback flag; OOM killers or supervisors killing the parent at the wrong moment.
Related errors
- writing confirmation bytes to %s: %v
- dialing confirmation address: %v
- loading initial config: %v
- making request: %v
- wrong confirmation: %x
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/43faac176539ce54.
Report an issue: GitHub.