{"record":{"id":"adc999e39a9d1e47","repo":"gohugoio/hugo","slug":"stopped-after-10-redirects","errorCode":null,"errorMessage":"stopped after 10 redirects","messagePattern":"stopped after 10 redirects","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/resource_factories/create/create.go","lineNumber":106,"sourceCode":"\thttpTimeout := 2 * time.Minute // Need to cover retries.\n\tif httpTimeout < (rs.Cfg.Timeout() + 30*time.Second) {\n\t\thttpTimeout = rs.Cfg.Timeout() + 30*time.Second\n\t}\n\n\treturn &Client{\n\t\trs:                    rs,\n\t\thttpCacheConfig:       httpCacheConfig,\n\t\tresourceIDDispatcher:  resourceIDDispatcher,\n\t\tremoteResourceChecker: remoteResourceChecker,\n\t\tremoteResourceLogger:  rs.Logger.InfoCommand(\"remote\"),\n\t\thttpClient: &http.Client{\n\t\t\tTimeout: httpTimeout,\n\t\t\tCheckRedirect: func(req *http.Request, via []*http.Request) error {\n\t\t\t\tif err := rs.ExecHelper.Sec().CheckAllowedHTTPURL(req.URL.String()); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif len(via) >= 10 {\n\t\t\t\t\treturn errors.New(\"stopped after 10 redirects\")\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t},\n\t\t\tTransport: &httpcache.Transport{\n\t\t\t\tCache: fileCache.AsHTTPCache(),\n\t\t\t\tCacheKey: func(req *http.Request) string {\n\t\t\t\t\treturn resourceIDDispatcher.Get(req.Context())\n\t\t\t\t},\n\t\t\t\tAround: func(req *http.Request, key string) func() {\n\t\t\t\t\treturn fileCache.NamedLock(key)\n\t\t\t\t},\n\t\t\t\tAlwaysUseCachedResponse: func(req *http.Request, key string) bool {\n\t\t\t\t\treturn !httpCacheConfig.For(req.URL.String())\n\t\t\t\t},\n\t\t\t\tShouldCache: func(req *http.Request, resp *http.Response, key string) bool {\n\t\t\t\t\treturn shouldCache(resp.StatusCode)\n\t\t\t\t},\n\t\t\t\tCanStore: func(reqCacheControl, respCacheControl httpcache.CacheControl) (canStore bool) {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/resources/resource_factories/create/create.go#L88-L124","documentation":"When fetching remote resources, Hugo's HTTP client sets a `CheckRedirect` cap of 10 hops (create.go:105-107) to prevent redirect loops. If a request follows 10 redirects and still isn't done, the client returns this error rather than following further.","triggerScenarios":"A `resources.GetRemote` (or similar remote-resource fetch) whose URL redirects more than 10 times before reaching a final 200 response — e.g. a misconfigured CDN, a redirect loop, or a chain of shortlink hops.","commonSituations":"Short URL services that chain many 301/302; a URL that bounces between http and https repeatedly; CDN misconfiguration causing loops; a moved resource whose redirect chain exceeds the cap.","solutions":["Resolve the final URL (follow redirects once with curl) and configure Hugo to fetch that final URL directly.","Fix the redirect loop/misconfiguration on the origin server.","Cache the resource locally and reference it as a local file if the remote is unstable."],"exampleFix":"# before\nresources.GetRemote \"https://short.url/abc\"\n\n# after: use the resolved final URL\nresources.GetRemote \"https://cdn.example.com/assets/abc.png\"","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"res, err := resources.GetRemote(url)\nif err != nil && strings.Contains(err.Error(), \"stopped after 10 redirects\") {\n    res, err = resources.GetRemote(resolvedFinalURL)\n}","preventionTips":["Resolve redirect chains upstream and store the final URL.","Cache flaky remote resources locally.","Watch origin CDN configuration for redirect loops."],"tags":["hugo","remote-resources","http","redirects"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}