{"record":{"id":"45f1d3a798467783","repo":"gohugoio/hugo","slug":"failed-to-read-remote-resource-q-w","errorCode":null,"errorMessage":"failed to read remote resource %q: %w","messagePattern":"failed to read remote resource %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/resource_factories/create/remote.go","lineNumber":298,"sourceCode":"\t\t\t// To cache this, we need to make sure the body is read.\n\t\t\tio.Copy(io.Discard, res.Body)\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tif res.StatusCode < 200 || res.StatusCode > 299 {\n\t\t\treturn nil, toHTTPError(fmt.Errorf(\"failed to fetch remote resource from '%s': %s\", uri, http.StatusText(res.StatusCode)), res, !isHeadMethod, options.ResponseHeaders)\n\t\t}\n\n\t\tvar (\n\t\t\tbody      []byte\n\t\t\tmediaType media.Type\n\t\t)\n\t\t// A response to a HEAD method should not have a body. If it has one anyway, that body must be ignored.\n\t\t// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD\n\t\tif !isHeadMethod && res.Body != nil {\n\t\t\tbody, err = io.ReadAll(res.Body)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to read remote resource %q: %w\", uri, err)\n\t\t\t}\n\t\t}\n\n\t\tfilename := path.Base(rURL.Path)\n\t\tif _, params, _ := mime.ParseMediaType(res.Header.Get(\"Content-Disposition\")); params != nil {\n\t\t\tif _, ok := params[\"filename\"]; ok {\n\t\t\t\tfilename = params[\"filename\"]\n\t\t\t}\n\t\t}\n\n\t\tcontentType := res.Header.Get(\"Content-Type\")\n\n\t\t// For HEAD requests we have no body to work with, so we need to use the Content-Type header.\n\t\tif isHeadMethod || c.rs.ExecHelper.Sec().HTTP.MediaTypes.Accept(contentType) {\n\t\t\tvar found bool\n\t\t\tmediaType, found = c.rs.MediaTypes().GetByType(contentType)\n\t\t\tif !found {\n\t\t\t\t// A media type not configured in Hugo, just create one from the content type string.","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/resources/resource_factories/create/remote.go#L280-L316","documentation":"Wrapped error from `Client.FromRemote` (remote.go:295-299) when `io.ReadAll(res.Body)` fails after a 2xx response. This is a mid-stream read failure on the response body -- the server returned a success status but the connection dropped or errored while streaming bytes. Distinct from 595 (status-level) and 598 (retry timeout).","triggerScenarios":"Server returns 200 but closes the connection mid-body; TLS renegotiation failure during transfer; proxy buffering timeout; client-side deadline (`context.WithTimeout`) firing mid-read; very large body exhausting memory and failing allocation.","commonSituations":"Flaky upstream behind a CDN that truncates large payloads; slow origin server hitting the configured `timeout` after headers; CI runner with constrained memory fetching a large asset; corporate proxy killing long streams; intermittent network blip mid-download.","solutions":["Raise the per-request `timeout` option so the read completes: `(dict \"timeout\" \"60s\")`.","For large assets, fetch and cache locally rather than streaming through Hugo.","Retry the build (transient mid-stream failures often clear); the retry loop only covers request establishment, not body read, so a re-run is needed.","If persistent, fetch the URL with `curl` from the build host to isolate server-side truncation.","Reduce body size (server-side pagination) or fetch a compressed variant."],"exampleFix":"// template -- before\n{{ $r := resources.GetRemote $url }}\n\n// after\n{{ $r := resources.GetRemote $url (dict \"timeout\" \"120s\") }}","handlingStrategy":"retry","validationCode":"// Head/probe to confirm a complete body is reachable.\n// (Doesn't fully prevent mid-stream drops but surfaces instability early.)","typeGuard":null,"tryCatchPattern":"// Retry on read-body failures.\nfor i := 0; i < 3; i++ {\n\tr, err := resources.GetRemote(url, opts)\n\tif err == nil || !strings.Contains(err.Error(), \"failed to read remote resource\") {\n\t\treturn r, err\n\t}\n\ttime.Sleep(time.Duration(i+1) * 2 * time.Second)\n}","preventionTips":["Set a generous `timeout` for large payloads.","Cache large remote assets locally between builds.","Monitor upstream stability; fall back to a committed copy when flaky."],"tags":["resources","remote","http","io","network"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}