{"record":{"id":"58d8c9f75ae62c3c","repo":"GopeedLab/gopeed","slug":"redirect-failed-58d8c9","errorCode":null,"errorMessage":"redirect failed","messagePattern":"redirect failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/download/engine/inject/stream/module.go","lineNumber":748,"sourceCode":"\t}()\n\treqBuilder := client.R()\n\treqBuilder.SetContext(ctx)\n\treqBuilder.DisableAutoReadResponse()\n\tfor _, header := range reqMeta.Headers {\n\t\treqBuilder.SetHeader(header[0], header[1])\n\t}\n\tif body != nil && reqMeta.Method != http.MethodGet && reqMeta.Method != http.MethodHead {\n\t\treqBuilder.SetBody(body)\n\t\tif contentType != \"\" && !hasHeader(reqMeta.Headers, \"Content-Type\") {\n\t\t\treqBuilder.SetHeader(\"Content-Type\", contentType)\n\t\t}\n\t}\n\tclient.SetRedirectPolicy(func(req *http.Request, via []*http.Request) error {\n\t\tswitch reqMeta.Redirect {\n\t\tcase \"manual\":\n\t\t\treturn http.ErrUseLastResponse\n\t\tcase \"error\":\n\t\t\treturn fmt.Errorf(\"redirect failed\")\n\t\tdefault:\n\t\t\tif len(via) > 20 {\n\t\t\t\treturn fmt.Errorf(\"too many redirects\")\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t})\n\tresp, err := reqBuilder.Send(reqMeta.Method, reqMeta.URL)\n\tif err != nil {\n\t\tvar ne net.Error\n\t\tif errorsAsTimeout(err, &ne) {\n\t\t\treturn nil, fmt.Errorf(\"Network request timed out\")\n\t\t}\n\t\treturn nil, fmt.Errorf(\"Network request failed: %w\", err)\n\t}\n\tid := fmt.Sprintf(\"%d\", time.Now().UnixNano())\n\tmeta := &fetchOpenMeta{\n\t\tID:         id,","sourceCodeStart":730,"sourceCodeEnd":766,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/pkg/download/engine/inject/stream/module.go#L730-L766","documentation":"In the injected fetch implementation, reqMeta.Redirect maps to the fetch() 'redirect' option. When the extension sets redirect:\"error\", the client's redirect policy returns this error for ANY 3xx response, mirroring the browser fetch spec where redirect:'error' rejects on a redirect. The error surfaces as a failed fetch wrapped in 'Network request failed'.","triggerScenarios":"gopeed.fetch(url, {redirect: 'error'}) where the server answers 301/302/303/307/308; resolving a short link or CDN URL that always redirects to a signed target while redirect mode is 'error'.","commonSituations":"Extension authors copying browser code that used redirect:'error' to detect hops; sites where the initial resolve URL is a permanent redirect to the canonical host; login flows that redirect to an auth domain.","solutions":["Use the default redirect:'follow' when you want the final response","Use redirect:'manual' to inspect the 3xx and its Location header yourself","Resolve the target URL first (follow once manually) and pass the final URL with redirect:'error'"],"exampleFix":"// before\nconst resp = await fetch(url, { redirect: 'error' }); // 302 -> redirect failed\n// after\nconst resp = await fetch(url, { redirect: 'follow' }); // or 'manual' to read Location","handlingStrategy":"validation","validationCode":"// JS: choose redirect mode deliberately before fetching\nconst REDIRECT = new Set(['follow', 'manual', 'error']);\nconst mode = REDIRECT.has(opts.redirect) ? opts.redirect : 'follow';\nif (mode === 'error') {\n  // preflight: a HEAD probe tells you if the URL redirects before you commit\n  const probe = await fetch(url, { method: 'HEAD', redirect: 'manual' });\n  if (probe.status >= 300 && probe.status < 400) throw new Error('URL redirects; use follow/manual');\n}\nconst resp = await fetch(url, { redirect: mode });","typeGuard":null,"tryCatchPattern":"try {\n  const resp = await fetch(url, { redirect: 'error' });\n} catch (e) {\n  if (String(e).includes('redirect failed')) {\n    const resp = await fetch(url, { redirect: 'manual' }); // fall back to manual handling\n  }\n}","preventionTips":["Default to 'follow'; reach for 'error' only to assert a URL is redirect-free","Resolve short links once during development and store the final URL","Remember the cap and modes mirror the browser fetch spec"],"tags":["network","fetch","redirect","http","extension"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}