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

  1. Do not invoke `caddy run --pingback` manually — it is reserved for the caddy start handshake
  2. If seen during caddy start, check whether a supervisor/OOM killer terminated the parent; free memory and retry
  3. 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

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


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