{"id":"22156780e75f8e0f","repo":"gohugoio/hugo","slug":"retry-timeout-configured-to-s-fetching-remote-r","errorCode":null,"errorMessage":"retry timeout (configured to %s) fetching remote resource: %s","messagePattern":"retry timeout \\(configured to (.+?)\\) fetching remote resource: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/resource_factories/create/remote.go","lineNumber":515,"sourceCode":"\n\t\tif retry {\n\t\t\tsleep := nextSleep\n\t\t\tretryAfter := parseRetryAfter(resp)\n\t\t\tif retryAfter > 0 {\n\t\t\t\tsleep = retryAfter\n\t\t\t}\n\t\t\tif start.IsZero() {\n\t\t\t\tstart = time.Now()\n\t\t\t}\n\t\t\tif d := time.Since(start) + sleep; d >= t.Cfg.Timeout() {\n\t\t\t\tmsg := \"<nil>\"\n\t\t\t\tif resp != nil {\n\t\t\t\t\tmsg = resp.Status\n\t\t\t\t}\n\t\t\t\tif retryAfter > 0 {\n\t\t\t\t\tmsg = fmt.Sprintf(\"%s (server requested Retry-After: %s)\", msg, retryAfter)\n\t\t\t\t}\n\t\t\t\terr := toHTTPError(fmt.Errorf(\"retry timeout (configured to %s) fetching remote resource: %s\", t.Cfg.Timeout(), msg), resp, req.Method != \"HEAD\", nil)\n\t\t\t\treturn resp, err\n\t\t\t}\n\t\t\ttime.Sleep(sleep)\n\t\t\tif nextSleep < nextSleepLimit {\n\t\t\t\tnextSleep *= 2\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\treturn\n\t}\n}\n\n// We need to send the redirect responses back to the HTTP client from RoundTrip,\n// but we don't want to cache them.\nfunc shouldCache(statusCode int) bool {\n\tswitch statusCode {\n\tcase http.StatusMovedPermanently, http.StatusFound, http.StatusSeeOther, http.StatusTemporaryRedirect, http.StatusPermanentRedirect:","sourceCodeStart":497,"sourceCodeEnd":533,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/resources/resource_factories/create/remote.go#L497-L533","documentation":"Hugo's resources.GetRemote retry loop gave up because the cumulative time spent retrying a remote fetch (elapsed plus the next planned sleep, including any server-sent Retry-After) reached the configured timeout. Hugo retries transient HTTP failures (429, 5xx) with exponential backoff, and this error caps total retry time so a build doesn't hang on a misbehaving endpoint. The message includes the last HTTP status ('<nil>' if no response) and the server's Retry-After when present.","triggerScenarios":"Calling resources.GetRemote (or css/js pipelines that fetch remote resources) against a URL that repeatedly returns retryable statuses (429/5xx) or errors, with total elapsed retry time + next sleep >= the timeout from security/httpcache config (default 1m). A server sending a Retry-After header longer than the remaining budget triggers it immediately.","commonSituations":"Rate-limited APIs (GitHub, font/CDN endpoints) returning 429 during CI builds with many parallel fetches; flaky or down remote hosts; a too-small custom timeout in site config; corporate proxies returning 503.","solutions":["Check the reported status: for 429, reduce fetch frequency or add authentication/tokens to raise the rate limit.","Increase the timeout, e.g. in hugo.toml: [HTTPCache]... or the resource-getting timeout option (timeout = \"2m\") for resources.GetRemote via the options map: {timeout = \"2m\"}.","Enable/configure the HTTP cache (caches / httpcache config) so repeated builds don't re-fetch the resource.","Verify the URL is reachable from the build environment (CI egress, proxy settings).","Wrap the fetch with try/with .Err handling in templates to fail gracefully: {{ with try (resources.GetRemote $url) }}...{{ end }}."],"exampleFix":"// before (template)\n{{ $r := resources.GetRemote \"https://api.example.com/data.json\" }}\n// after: longer timeout + error handling\n{{ $opts := dict \"timeout\" \"2m\" }}\n{{ with try (resources.GetRemote \"https://api.example.com/data.json\" $opts) }}\n  {{ with .Err }}{{ warnf \"%s\" . }}{{ else }}{{ .Value.Content }}{{ end }}\n{{ end }}","handlingStrategy":"retry","validationCode":"// config.toml — size timeout to the slowest expected endpoint\n// [security.http] / resources.GetRemote options:\n// {{ $opts := dict \"responseHeaders\" true }}\n// timeout = \"60s\"  # in [imaging]/site config: resourceGetRemote timeout via `timeout` key","typeGuard":null,"tryCatchPattern":"{{ with try (resources.GetRemote $url) }}\n  {{ with .Err }}{{ warnf \"remote fetch failed: %s\" . }}{{ else }}{{ with .Value }}{{ .RelPermalink }}{{ end }}{{ end }}\n{{ end }}","preventionTips":["Raise the `timeout` site config value for slow remote hosts","Always check `.Err` on resources.GetRemote instead of using the result directly","Cache remote resources (resources cache dir) so CI rebuilds don't refetch","Prefer stable CDN URLs; avoid endpoints with rate limits"],"tags":["network","remote-resources","timeout","retry","hugo"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}