caddyserver/caddy · error

wrong confirmation: %x

Error message

wrong confirmation: %x

What it means

Internal fork/exec handshake: after spawning a child (e.g. 'caddy run' unsupervised start), the parent reads up to 32 confirmation bytes from a pipe and compares them to the expected token. A mismatch (including zero bytes if the child died) produces 'wrong confirmation' with the actual bytes hex-encoded.

Source

Thrown at cmd/main.go:90

	if err := defaultFactory.Build().Execute(); err != nil {
		var exitError *exitError
		if errors.As(err, &exitError) {
			os.Exit(exitError.ExitCode)
		}
		os.Exit(1)
	}
}

// handlePingbackConn reads from conn and ensures it matches
// the bytes in expect, or returns an error if it doesn't.
func handlePingbackConn(conn net.Conn, expect []byte) error {
	defer conn.Close()
	confirmationBytes, err := io.ReadAll(io.LimitReader(conn, 32))
	if err != nil {
		return err
	}
	if !bytes.Equal(confirmationBytes, expect) {
		return fmt.Errorf("wrong confirmation: %x", confirmationBytes)
	}
	return nil
}

// LoadConfig loads the config from configFile and adapts it
// using adapterName. If adapterName is specified, configFile
// must be also. If no configFile is specified, it tries
// loading a default config file. The lack of a config file is
// not treated as an error, but false will be returned if
// there is no config available. It prints any warnings to stderr,
// and returns the resulting JSON config bytes along with
// the name of the loaded config file (if any).
// The return values are:
//   - config bytes (nil if no config)
//   - config file used ("" if none)
//   - adapter used ("" if none)
//   - error, if any
func LoadConfig(configFile, adapterName string) ([]byte, string, string, error) {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Run 'caddy run' in the foreground to see the child's real startup error
  2. Validate the config first: caddy validate --config <file>
  3. Check logs (journalctl -u caddy or the configured log) for the child's panic/error

Example fix

# before
caddy start   # wrong confirmation: (empty)

# after (foreground exposes the true error)
caddy run --config /etc/caddy/Caddyfile
Defensive patterns

Strategy: fallback

Validate before calling

# Verify the config before backgrounded start so the child confirms cleanly:
caddy validate --config /etc/caddy/Caddyfile && caddy start --config /etc/caddy/Caddyfile

Try / catch

if err := caddyStart(); err != nil { if strings.Contains(err.Error(), "wrong confirmation") { /* fall back to foreground 'caddy run' to expose the child's real error */ } }

Prevention

When it happens

Trigger: Child process crashes before writing its pingback token, writes garbage, or the pipe is closed early. Users see this as a startup failure right after 'caddy start'/'caddy run' forks.

Common situations: The child failing during early init (bad config, bind failure) so it never confirms; exotic environments (restricted containers) where the inherited pipe behaves unusually.

Related errors


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