caddyserver/caddy · error
starting caddy administration endpoint: %v
Error message
starting caddy administration endpoint: %v
What it means
When a config change alters admin endpoint settings, run() calls replaceLocalAdminServer to tear down the old admin listener and bind the new one. Any failure — the new address cannot be parsed/bound, port in use, permission denied — is wrapped as 'starting caddy administration endpoint'. Because this happens inside the load, the whole config change fails and the old state is restored.
Source
Thrown at caddy.go:568
newCfg.storage = stor
}
if newCfg.storage == nil {
newCfg.storage = DefaultStorage
}
certmagic.Default.Storage = newCfg.storage
return nil
}()
if err != nil {
return ctx, err
}
// start the admin endpoint (and stop any prior one)
if replaceAdminServer {
err = replaceLocalAdminServer(newCfg, ctx)
if err != nil {
return ctx, fmt.Errorf("starting caddy administration endpoint: %v", err)
}
}
// Load and Provision each app and their submodules
err = func() error {
for appName := range newCfg.AppsRaw {
if _, err := ctx.App(appName); err != nil {
return err
}
}
return nil
}()
return ctx, err
}
// ProvisionContext creates a new context from the configuration and provisions storage
// and app modules.
// The function is intended for testing and advanced use cases only, typically `Run` should beView on GitHub (pinned to 50e54ee279)
Solutions
- Check the wrapped error — it names the bind failure and address.
- Free the target port or pick another one; for unix sockets, mkdir -p the parent dir and check permissions.
- For privileged ports grant cap_net_bind_service or run from systemd with the capability.
- Keep the admin address stable across config loads unless a change is really needed.
Example fix
// before
"admin": { "listen": "unix//run/caddy/admin.sock" } // /run/caddy missing
// after (ensure dir exists)
mkdir -p /run/caddy && chown caddy /run/caddy # then reload Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight the admin bind before loading a config that changes it.
if cfg.Admin.Listen != "" {
na, err := caddy.ParseNetworkAddress(cfg.Admin.Listen)
if err != nil || na.PortRangeSize() != 1 { return errors.New("bad admin address") }
ln, err := net.Listen(na.Network, na.JoinHostPort(0, 0))
if err != nil { return fmt.Errorf("admin bind would fail: %w", err) }
ln.Close()
} Prevention
- Avoid changing admin.listen in routine config pushes; pin it once.
- Create unix socket directories with correct ownership before deploy.
- Check port occupancy and capabilities before switching admin ports.
When it happens
Trigger: Loading a config whose admin.listen changes to an address already bound by another process or the current admin server in a way that can't be transitioned; binding a privileged port without capability; unix socket path whose directory does not exist; remote admin ('remote_admin') TLS material being invalid.
Common situations: Repointing admin to a unix socket with a missing /run/caddy directory; another service squatting on the target port; SELinux denying the socket bind; changing admin origin/host to an interface Caddy cannot bind.
Related errors
- unknown object ID '%s'
- decoding request body: %w, at offset %d
- decoding request body: %w
- no traversable path
- path missing
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/fcad007518546d40.
Report an issue: GitHub.