{"record":{"id":"e5d53a5991e28f05","repo":"caddyserver/caddy","slug":"download-and-error-decoding-failed-http-d-v","errorCode":null,"errorMessage":"download and error decoding failed: HTTP %d: %v","messagePattern":"download and error decoding failed: HTTP (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/packagesfuncs.go","lineNumber":300,"sourceCode":"\tl.Info(\"requesting build\",\n\t\tzap.String(\"os\", qs.Get(\"os\")),\n\t\tzap.String(\"arch\", qs.Get(\"arch\")),\n\t\tzap.Strings(\"packages\", qs[\"p\"]))\n\tresp, err := http.Get(fmt.Sprintf(\"%s?%s\", downloadPath, qs.Encode()))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"secure request failed: %v\", err)\n\t}\n\tif resp.StatusCode >= 400 {\n\t\tvar details struct {\n\t\t\tStatusCode int `json:\"status_code\"`\n\t\t\tError      struct {\n\t\t\t\tMessage string `json:\"message\"`\n\t\t\t\tID      string `json:\"id\"`\n\t\t\t} `json:\"error\"`\n\t\t}\n\t\terr2 := json.NewDecoder(resp.Body).Decode(&details)\n\t\tif err2 != nil {\n\t\t\treturn nil, fmt.Errorf(\"download and error decoding failed: HTTP %d: %v\", resp.StatusCode, err2)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"download failed: HTTP %d: %s (id=%s)\", resp.StatusCode, details.Error.Message, details.Error.ID)\n\t}\n\treturn resp, nil\n}\n\nfunc getPluginPackages(modules []moduleInfo) (map[string]pluginPackage, error) {\n\tpluginPkgs := make(map[string]pluginPackage)\n\tfor _, mod := range modules {\n\t\tif mod.goModule.Replace != nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot auto-upgrade when Go module has been replaced: %s => %s\",\n\t\t\t\tmod.goModule.Path, mod.goModule.Replace.Path)\n\t\t}\n\t\tpluginPkgs[mod.goModule.Path] = pluginPackage{Version: mod.goModule.Version, Path: mod.goModule.Path}\n\t}\n\treturn pluginPkgs, nil\n}\n","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/cmd/packagesfuncs.go#L282-L318","documentation":"The download API returned HTTP >= 400, and when caddy tried to JSON-decode the error body ({status_code, error:{message,id}}) the decode itself failed. So two problems stacked: an HTTP error status and a body that is not the expected JSON error document — typically an HTML error page from a proxy, CDN, or captive portal.","triggerScenarios":"A reverse proxy/CDN in front of caddyserver.com returning an HTML 502/503; a captive portal returning a 400 with an HTML login page; a truncated body causing EOF during decode; a WAF rewriting error responses.","commonSituations":"caddyserver.com briefly down behind Cloudflare returning HTML error pages; corporate proxy injecting an HTML block page for the download API.","solutions":["Retry after a short wait — API-side 5xx with HTML error pages are usually transient","Check the exact status/body manually: curl -i with the same query string to see what is actually returned","If a proxy is rewriting responses, bypass it or whitelist caddyserver.com","Check status.caddyserver.com / community channels for build API outages"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"curl -s -o /dev/null -w '%{http_code} %{content_type}\\n' 'https://caddyserver.com/api/download?os=linux&arch=amd64'\n# expect 200 application/json (or a JSON error); text/html means a proxy/CDN page — investigate","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Retry after a minute for API/CDN transient errors","Whitelist caddyserver.com on content-filtering proxies","Keep a known-good caddy binary on hand so upgrades are never urgent"],"tags":["network","http","api","upgrade"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}