Hmbown/CodeWhale · error

bundle fetch exceeded the five-redirect limit

Error message

bundle fetch exceeded the five-redirect limit

What it means

`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.

Solutions

  1. Use the final, direct bundle URL (the one that returns 200) instead of the redirecting one.
  2. Fix the redirect loop on the server hosting the bundle.
  3. Retry later if the remote is temporarily misconfigured; or download the bundle manually with curl and import the local file.

Example fix

// before
codewhale config bundle import https://short.link/abc
// after
codewhale config bundle import https://releases.example.com/bundles/config.zip
Defensive patterns

Strategy: try-catch

Try / catch

match fetch_result {
    Err(e) if e.to_string().contains("five-redirect limit") => {
        eprintln!("remote is redirect-looping; use the direct bundle URL");
    }
    Err(e) => return Err(e),
    Ok(bytes) => apply(bytes),
}

Prevention

When it happens

Trigger: Running `codewhale config bundle import <url>` where the server responds with a sixth redirection (3xx with Location header after five hops already followed).

Common situations: A misconfigured remote host with a redirect loop; short-link services chained through too many hops; a staging mirror that bounces between two URLs.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/524cbfb08a56813d. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/config_bundles.rs:778

        // Redirect targets must pass the same scheme/host policy as the
        // initial request, so redirects are followed explicitly below.
        .redirect(reqwest::redirect::Policy::none())
        .build()
        .map_err(|_| anyhow!("building bundle fetch client failed"))?;
    let mut redirects = 0usize;
    let response = loop {
        let response = client
            .get(current_url.clone())
            .send()
            // reqwest errors can include the full URL (including its query or
            // userinfo), so keep transport failures deliberately URL-free.
            .map_err(|_| anyhow!("bundle fetch request failed"))?;

        if !response.status().is_redirection() {
            break response;
        }
        if redirects >= MAX_REDIRECTS {
            bail!("bundle fetch exceeded the five-redirect limit");
        }
        let location = response
            .headers()
            .get(reqwest::header::LOCATION)
            .ok_or_else(|| anyhow!("bundle redirect is missing a valid Location header"))?
            .to_str()
            .map_err(|_| anyhow!("bundle redirect is missing a valid Location header"))?;
        let next_url = current_url
            .join(location)
            .map_err(|_| anyhow!("bundle redirect Location is invalid"))?;
        validate_bundle_redirect(&initial_scheme, &next_url)?;
        current_url = next_url;
        redirects += 1;
    };

    if !response.status().is_success() {
        bail!(
            "bundle fetch failed with HTTP status {}",

View on GitHub (pinned to 73e0f67d83)