{"id":"73edc44a7de603b1","repo":"gohugoio/hugo","slug":"failed-to-fetch-remote-resource-from-s-s","errorCode":null,"errorMessage":"failed to fetch remote resource from '%s': %s","messagePattern":"failed to fetch remote resource from '(.+?)': (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/resource_factories/create/remote.go","lineNumber":286,"sourceCode":"\t\tif cancel != nil {\n\t\t\tdefer cancel()\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdefer res.Body.Close()\n\n\t\tc.configurePollingIfEnabled(uri, optionsKey, getRes)\n\n\t\tif res.StatusCode == http.StatusNotFound {\n\t\t\t// Not found. This matches how lookups for local resources work.\n\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 {","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/resources/resource_factories/create/remote.go#L268-L304","documentation":"The remote fetch completed but the server answered with a non-2xx status (other than 404, which Hugo maps to a nil resource to mirror missing local resources). Hugo wraps the status text into an HTTP error carrying the response so templates can inspect it via `.Err`. This is a server-side/authorization problem, not a Hugo bug.","triggerScenarios":"`resources.GetRemote` receiving 401/403 (missing or invalid auth headers), 429 (rate limiting, common with GitHub/API endpoints during CI builds), 5xx from the origin, or 3xx loops the client won't follow — anything outside 200–299 except 404.","commonSituations":"Expired or unset API tokens in CI environment variables, GitHub API rate limits on unauthenticated builds, hotlink protection or bot blocking (Cloudflare 403) against Hugo's requests, endpoints requiring a User-Agent header, or transient upstream outages during site builds.","solutions":["Handle it gracefully in the template: check `.Err` on the returned resource (`{{ with try (resources.GetRemote $u) }}...`) and log via `errorf`/`warnf` instead of crashing the build.","Add required auth/User-Agent headers via the options dict and ensure CI secrets are actually set.","For 429s, authenticate to raise rate limits or cache the response (use a stable `key` option) so rebuilds don't refetch.","Verify the URL responds correctly with `curl -i` from the same environment as the build."],"exampleFix":"{{/* before */}}\n{{ $data := resources.GetRemote $u | transform.Unmarshal }}\n{{/* after */}}\n{{ with resources.GetRemote $u (dict \"headers\" (dict \"Authorization\" (printf \"Bearer %s\" (getenv \"API_TOKEN\")))) }}\n  {{ with .Err }}{{ errorf \"remote fetch failed: %s\" . }}{{ else }}{{ $data := . | transform.Unmarshal }}{{ end }}\n{{ end }}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"{{/* GetRemote does not fail the build by default — check .Err yourself */}}\n{{ $r := resources.GetRemote $url }}\n{{ with $r }}\n  {{ with .Err }}\n    {{ warnf \"remote fetch failed: %s — using local fallback\" . }}\n    {{ $r = resources.Get \"fallback/placeholder.svg\" }}\n  {{ end }}\n{{ end }}","preventionTips":["Always check .Err on the result of resources.GetRemote; a non-2xx status surfaces there","Decide explicitly per call: errorf (fail build) for critical assets, warnf + committed local fallback for optional ones — Hugo builds are offline-hostile in CI","Cache remote resources (resources/_gen committed or CI cache) so transient upstream outages don't break builds","Send required auth headers; 401/403 responses appear as this fetch error"],"tags":["hugo","get-remote","http-status","network","ci"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}