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
- Run 'caddy run' in the foreground to see the child's real startup error
- Validate the config first: caddy validate --config <file>
- 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
- Prefer 'caddy run' in the foreground while iterating on configs
- Validate configs before 'caddy start' — the pingback masks the child's init failure
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
- caddy process exited with error: %v
- loading initial config: %v
- reading confirmation bytes from stdin: %v
- writing confirmation bytes to %s: %v
- making request: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/25e258f284941e23.
Report an issue: GitHub.