caddyserver/caddy · error
performing request: %v
Error message
performing request: %v
What it means
Wraps the error from client.Do in AdminAPIRequest: the CLI could not complete the HTTP round-trip to the admin endpoint. Typical causes are connection refused (Caddy not running or admin disabled), timeouts, or dialing a unix socket path that does not exist or has wrong permissions.
Source
Thrown at cmd/commandfuncs.go:841
if body != nil {
req.Header.Set("Content-Type", "application/json")
}
maps.Copy(req.Header, headers)
// make an HTTP client that dials our network type, since admin
// endpoints aren't always TCP, which is what the default transport
// expects; reuse is not of particular concern here
client := http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial(parsedAddr.Network, parsedAddr.JoinHostPort(0))
},
},
}
resp, err := client.Do(req) //nolint:gosec // the only SSRF here would be self-sabotage I think
if err != nil {
return nil, fmt.Errorf("performing request: %v", err)
}
// if it didn't work, let the user know
if resp.StatusCode >= 400 {
respBody, err := io.ReadAll(io.LimitReader(resp.Body, 1024*1024*2))
if err != nil {
return nil, fmt.Errorf("HTTP %d: reading error message: %v", resp.StatusCode, err)
}
return nil, fmt.Errorf("caddy responded with error: HTTP %d: %s", resp.StatusCode, respBody)
}
return resp, nil
}
// DetermineAdminAPIAddress determines which admin API endpoint address should
// be used based on the inputs. By priority: if `address` is specified, then
// it is returned; if `config` is specified, then that config will be used for
// finding the admin address; if `configFile` (and `configAdapter`) are specified,View on GitHub (pinned to 50e54ee279)
Solutions
- Verify Caddy is running: systemctl status caddy or curl http://localhost:2019/config/
- Omit --address so the CLI discovers the admin address from the config file
- Check the admin.listen value in your config and match the CLI flags to it
- For unix sockets, ensure the CLI runs as a user with permission on the socket file
Example fix
# before (admin listens on unix socket per config, CLI guesses TCP default) caddy reload --address localhost:2019 # after (let the CLI read admin.listen from the config) caddy reload --config /etc/caddy/Caddyfile
Defensive patterns
Strategy: retry
Validate before calling
# Check reachability before issuing the CLI command: curl -fsS http://localhost:2019/config/ >/dev/null || echo "admin API not reachable"
Try / catch
if err := cmdReload(); err != nil { if strings.Contains(err.Error(), "performing request") { log.Printf("daemon unreachable: %v — is caddy running?", err) } return err } Prevention
- Health-check the admin endpoint in scripts before reload/stop
- Let the CLI discover the admin address from the config instead of hardcoding --address
- Keep CLI user and daemon user aligned when using unix admin sockets
When it happens
Trigger: Running 'caddy reload', 'caddy stop', or similar while the Caddy daemon is not running; admin endpoint listening on a different address than --address specifies; admin config set to listen on a unix socket the CLI user cannot access; firewall blocking localhost port.
Common situations: 'caddy reload' after the service crashed or was stopped; running the CLI as a different user than the daemon when the admin socket has restrictive permissions; custom admin.listen set in config but not passed to the CLI (omit --address so it is read from the config).
Related errors
- reading request body: %v
- opening listener for success confirmation: %v
- listen on 127.0.0.1:0: %v; listen on [::1]:0: %v
- dialing confirmation address: %v
- writing confirmation bytes to %s: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/46065fa8d468f6a6.
Report an issue: GitHub.