{"record":{"id":"86dfd811e92c4b09","repo":"mislav/hub","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":"github/http.go","lineNumber":231,"sourceCode":"\tvar recommendedCode int\n\tswitch req.Response.StatusCode {\n\tcase 301:\n\t\trecommendedCode = 308\n\tcase 302:\n\t\trecommendedCode = 307\n\t}\n\n\torigMethod := via[len(via)-1].Method\n\tif recommendedCode != 0 && !strings.EqualFold(req.Method, origMethod) {\n\t\treturn fmt.Errorf(\n\t\t\t\"refusing to follow HTTP %d redirect for a %s request\\n\"+\n\t\t\t\t\"Have your site admin use HTTP %d for this kind of redirect\",\n\t\t\treq.Response.StatusCode, origMethod, recommendedCode)\n\t}\n\n\t// inherited from stdlib defaultCheckRedirect\n\tif len(via) >= 10 {\n\t\treturn errors.New(\"stopped after 10 redirects\")\n\t}\n\treturn nil\n}\n\nfunc cloneRequest(req *http.Request) *http.Request {\n\tdup := new(http.Request)\n\t*dup = *req\n\tdup.URL, _ = url.Parse(req.URL.String())\n\tdup.Header = make(http.Header)\n\tfor k, s := range req.Header {\n\t\tdup.Header[k] = s\n\t}\n\treturn dup\n}\n\nvar proxyFunc func(*url.URL) (*url.URL, error)\n\nfunc proxyFromEnvironment(req *http.Request) (*url.URL, error) {","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/mislav/hub/blob/5c547ed804368763064e51f3990851e267e88edd/github/http.go#L213-L249","documentation":"hub installs a custom checkRedirect on its HTTP client. Inherited from the stdlib defaultCheckRedirect, it returns this error once a request has followed 10 or more redirects (the `via` slice tracks the redirect chain). It guards against redirect loops or misconfigured servers that keep redirecting.","triggerScenarios":"A GitHub Enterprise host (or proxy) responds with a chain of more than 10 HTTP redirects — typically a redirect loop, e.g. http->https misconfiguration where the server keeps 301/302-ing back to itself or cycling between URLs.","commonSituations":"GitHub Enterprise behind a reverse proxy with conflicting ssl termination; http:// URL configured for a server that forces https and the https endpoint redirects back; corporate proxy loops; a webhook/upload_url pointing at itself.","solutions":["Switch your hub GitHub host config from http:// to https:// (or the scheme the server actually serves) to break the scheme-redirect loop.","Check the server's redirect chain with `curl -IL <url>` and fix the proxy/load-balancer configuration causing the loop.","If a proxy is involved, set NO_PROXY/correct proxy env vars so hub talks to the right endpoint directly."],"exampleFix":"// before (~/.config/hub config)\ngithub.com:\n  - api_host: http://ghe.example.com\n// after\ngithub.com:\n  - api_host: https://ghe.example.com","handlingStrategy":"validation","validationCode":"// Check the endpoint's redirect chain before configuring hub:\n// curl -sIL --max-redirs 15 https://ghe.example.com/api/v3 | grep -i location\n// If it loops, fix the server config; if it bounces http->https, use https in hub config.\n","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"stopped after 10 redirects\") {\n        // surface hint: likely http/https redirect loop on the GHE host\n    }\n    return err\n}","preventionTips":["Always configure https:// hosts for GitHub Enterprise.","Test proxy/SSL configs with curl -IL before rolling out.","Avoid mixed http/https listeners on the same GHE host.","Set proxy env vars (HTTPS_PROXY/NO_PROXY) correctly in CI."],"tags":["http","redirects","network"],"backgroundTag":"too-many-redirects","analyzedSha":"5c547ed804368763064e51f3990851e267e88edd","analyzedAt":"2026-09-01T03:34:15.525Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}