{"record":{"id":"8ab6a764ee873ec9","repo":"caddyserver/caddy","slug":"download-failed-v","errorCode":null,"errorMessage":"download failed: %v","messagePattern":"download failed: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/packagesfuncs.go","lineNumber":158,"sourceCode":"\t\t\treturn caddy.ExitCodeFailedStartup, fmt.Errorf(\"resolving current executable symlink: %v\", err)\n\t\t}\n\t\tl.Info(\"this executable is a symlink\", zap.String(\"source\", symSource), zap.String(\"target\", thisExecPath))\n\t}\n\tl.Info(\"this executable will be replaced\", zap.String(\"path\", thisExecPath))\n\n\t// build the request URL to download this custom build\n\tqs := url.Values{\n\t\t\"os\":   {runtime.GOOS},\n\t\t\"arch\": {runtime.GOARCH},\n\t}\n\tfor _, pkgInfo := range pluginPkgs {\n\t\tqs.Add(\"p\", pkgInfo.String())\n\t}\n\n\t// initiate the build\n\tresp, err := downloadBuild(qs)\n\tif err != nil {\n\t\treturn caddy.ExitCodeFailedStartup, fmt.Errorf(\"download failed: %v\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\t// back up the current binary, in case something goes wrong we can replace it\n\tbackupExecPath := thisExecPath + \".tmp\"\n\tl.Info(\"build acquired; backing up current executable\",\n\t\tzap.String(\"current_path\", thisExecPath),\n\t\tzap.String(\"backup_path\", backupExecPath))\n\terr = os.Rename(thisExecPath, backupExecPath)\n\tif err != nil {\n\t\treturn caddy.ExitCodeFailedStartup, fmt.Errorf(\"backing up current binary: %v\", err)\n\t}\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr2 := os.Rename(backupExecPath, thisExecPath)\n\t\t\tif err2 != nil {\n\t\t\t\tl.Error(\"restoring original executable failed; will need to be restored manually\",\n\t\t\t\t\tzap.String(\"backup_path\", backupExecPath),","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/cmd/packagesfuncs.go#L140-L176","documentation":"upgradeBuild failed to obtain a custom build from the download API (https://caddyserver.com/api/download). downloadBuild performs an HTTP GET with os/arch and the package list; this wrapper fires on transport errors ('secure request failed: ...') or HTTP >= 400 responses from the API (bad/unknown module, version that doesn't exist, build server error), with the API's decoded message embedded. Note this mechanism requires internet access to caddyserver.com — builds are produced server-side, not locally.","triggerScenarios":"`caddy upgrade`, `caddy add-package`, or `caddy remove-package` with no route to caddyserver.com (offline host, blocked egress, DNS failure, TLS-intercepting proxy); or requesting a module/version the API cannot resolve (typo, yanked version, private repo).","commonSituations":"Hardened servers and air-gapped environments where the build API is unreachable; corporate proxies whose MITM certificate chain Caddy doesn't trust; adding a plugin from a private repository; caddyserver.com being down or rate-limiting.","solutions":["Read the nested error: 'secure request failed' indicates a network/TLS problem; 'HTTP 4xx/5xx ... message' indicates a bad request — fix the module path/version it names","Check connectivity: `curl -I 'https://caddyserver.com/api/download?os=linux&arch=amd64'`; fix DNS, egress rules, or proxy env (HTTPS_PROXY) as needed","For private/unpublishable modules or offline hosts, build locally with xcaddy instead of the download API","Verify the exact module path and a published version tag exist on the Go module proxy (proxy.golang.org)"],"exampleFix":"# before (offline / private module)\ncaddy add-package github.com/corp/private-plugin  # download failed: HTTP 400\n\n# after\nxcaddy build --with github.com/corp/private-plugin","handlingStrategy":"retry","validationCode":"curl -fsSI --max-time 10 'https://caddyserver.com/api/download?os=linux&arch=amd64' >/dev/null \\\n  && echo 'download API reachable' \\\n  || echo 'API unreachable; fix network or use xcaddy build --with <module>'","typeGuard":null,"tryCatchPattern":"# shell: run upgrade, fall back to xcaddy on network failure\nif ! caddy upgrade; then\n  echo 'in-place upgrade failed; falling back to xcaddy' >&2\n  xcaddy build --with github.com/caddy-dns/cloudflare\nfi","preventionTips":["Ensure egress to caddyserver.com (and trusted TLS) on hosts that use upgrade/add-package","Use xcaddy for offline, proxied, or private-module environments","Pin plugin versions that exist on proxy.golang.org to avoid HTTP 400 from the build API"],"tags":["caddy","upgrade","network","download-api","cli","packages"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}