{"record":{"id":"46065fa8d468f6a6","repo":"caddyserver/caddy","slug":"performing-request-v","errorCode":null,"errorMessage":"performing request: %v","messagePattern":"performing request: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/commandfuncs.go","lineNumber":841,"sourceCode":"\tif body != nil {\n\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\t}\n\tmaps.Copy(req.Header, headers)\n\n\t// make an HTTP client that dials our network type, since admin\n\t// endpoints aren't always TCP, which is what the default transport\n\t// expects; reuse is not of particular concern here\n\tclient := http.Client{\n\t\tTransport: &http.Transport{\n\t\t\tDialContext: func(_ context.Context, _, _ string) (net.Conn, error) {\n\t\t\t\treturn net.Dial(parsedAddr.Network, parsedAddr.JoinHostPort(0))\n\t\t\t},\n\t\t},\n\t}\n\n\tresp, err := client.Do(req) //nolint:gosec // the only SSRF here would be self-sabotage I think\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"performing request: %v\", err)\n\t}\n\n\t// if it didn't work, let the user know\n\tif resp.StatusCode >= 400 {\n\t\trespBody, err := io.ReadAll(io.LimitReader(resp.Body, 1024*1024*2))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"HTTP %d: reading error message: %v\", resp.StatusCode, err)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"caddy responded with error: HTTP %d: %s\", resp.StatusCode, respBody)\n\t}\n\n\treturn resp, nil\n}\n\n// DetermineAdminAPIAddress determines which admin API endpoint address should\n// be used based on the inputs. By priority: if `address` is specified, then\n// it is returned; if `config` is specified, then that config will be used for\n// finding the admin address; if `configFile` (and `configAdapter`) are specified,","sourceCodeStart":823,"sourceCodeEnd":859,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/cmd/commandfuncs.go#L823-L859","documentation":"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.","triggerScenarios":"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.","commonSituations":"'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).","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"],"exampleFix":"# before (admin listens on unix socket per config, CLI guesses TCP default)\ncaddy reload --address localhost:2019\n\n# after (let the CLI read admin.listen from the config)\ncaddy reload --config /etc/caddy/Caddyfile","handlingStrategy":"retry","validationCode":"# Check reachability before issuing the CLI command:\ncurl -fsS http://localhost:2019/config/ >/dev/null || echo \"admin API not reachable\"","typeGuard":null,"tryCatchPattern":"if err := cmdReload(); err != nil { if strings.Contains(err.Error(), \"performing request\") { log.Printf(\"daemon unreachable: %v — is caddy running?\", err) } return err }","preventionTips":["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"],"tags":["cli","admin-api","network","connection-refused"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}