{"record":{"id":"524cbfb08a56813d","repo":"Hmbown/CodeWhale","slug":"bundle-fetch-exceeded-the-five-redirect-limit","errorCode":null,"errorMessage":"bundle fetch exceeded the five-redirect limit","messagePattern":"bundle fetch exceeded the five-redirect limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/config_bundles.rs","lineNumber":778,"sourceCode":"        // Redirect targets must pass the same scheme/host policy as the\n        // initial request, so redirects are followed explicitly below.\n        .redirect(reqwest::redirect::Policy::none())\n        .build()\n        .map_err(|_| anyhow!(\"building bundle fetch client failed\"))?;\n    let mut redirects = 0usize;\n    let response = loop {\n        let response = client\n            .get(current_url.clone())\n            .send()\n            // reqwest errors can include the full URL (including its query or\n            // userinfo), so keep transport failures deliberately URL-free.\n            .map_err(|_| anyhow!(\"bundle fetch request failed\"))?;\n\n        if !response.status().is_redirection() {\n            break response;\n        }\n        if redirects >= MAX_REDIRECTS {\n            bail!(\"bundle fetch exceeded the five-redirect limit\");\n        }\n        let location = response\n            .headers()\n            .get(reqwest::header::LOCATION)\n            .ok_or_else(|| anyhow!(\"bundle redirect is missing a valid Location header\"))?\n            .to_str()\n            .map_err(|_| anyhow!(\"bundle redirect is missing a valid Location header\"))?;\n        let next_url = current_url\n            .join(location)\n            .map_err(|_| anyhow!(\"bundle redirect Location is invalid\"))?;\n        validate_bundle_redirect(&initial_scheme, &next_url)?;\n        current_url = next_url;\n        redirects += 1;\n    };\n\n    if !response.status().is_success() {\n        bail!(\n            \"bundle fetch failed with HTTP status {}\",","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/config_bundles.rs#L760-L796","documentation":"`fetch_bundle` followed HTTP redirects while importing a bundle from a URL and hit `MAX_REDIRECTS` (five). The fetch aborts rather than looping indefinitely, guarding against redirect loops and open-redirect chains on the remote host.","triggerScenarios":"Running `codewhale config bundle import <url>` where the server responds with a sixth redirection (3xx with Location header after five hops already followed).","commonSituations":"A misconfigured remote host with a redirect loop; short-link services chained through too many hops; a staging mirror that bounces between two URLs.","solutions":["Use the final, direct bundle URL (the one that returns 200) instead of the redirecting one.","Fix the redirect loop on the server hosting the bundle.","Retry later if the remote is temporarily misconfigured; or download the bundle manually with curl and import the local file."],"exampleFix":"// before\ncodewhale config bundle import https://short.link/abc\n// after\ncodewhale config bundle import https://releases.example.com/bundles/config.zip","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match fetch_result {\n    Err(e) if e.to_string().contains(\"five-redirect limit\") => {\n        eprintln!(\"remote is redirect-looping; use the direct bundle URL\");\n    }\n    Err(e) => return Err(e),\n    Ok(bytes) => apply(bytes),\n}","preventionTips":["Use direct, canonical URLs for bundle distribution.","Check servers hosting bundles for redirect loops with `curl -IL`.","Avoid short-link services when sharing bundle URLs."],"tags":["http","redirects","bundle-fetch"],"backgroundTag":"http-request-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T21:17:16.096Z"}