Hmbown/CodeWhale · error

bundle redirect Location is invalid

Error message

bundle redirect Location is invalid

What it means

The Location header from a redirect could not be resolved against the current URL by url::Url::join — typically a relative reference that cannot be parsed in context or a structurally malformed URL. fetch_bundle validates each hop before following it, so a broken target is refused before any request is made.

Solutions

  1. Fix the server to emit a syntactically valid absolute or properly relative Location URL.
  2. Use the final bundle URL directly to skip redirects.
  3. Check the next_url produced by the redirector for missing scheme or host.

Example fix

// before (server)
Location: ftp:// or http://
// after (server)
Location: https://host/path/bundle.toml
Defensive patterns

Strategy: validation

Validate before calling

let parsed = url::Url::parse(location_header).or_else(|_| base.join(location_header)); if parsed.is_err() { eprintln!("server emitted unusable Location: {:?}", location_header); }

Try / catch

match fetch_bundle(url) { Err(e) if e.to_string().contains("Location is invalid") => eprintln!("fix or bypass the redirector"), other => other?, }

Prevention

When it happens

Trigger: Redirect Location value like 'http://' or otherwise malformed, making current_url.join(location) return Err while following bundle redirects.

Common situations: Misconfigured web servers emitting garbage Location values, proxies injecting invalid URLs, hand-written redirect handlers producing wrong relative paths.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

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

            // 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 {}",
            response.status().as_u16()
        );
    }

    // Read at most MAX_BUNDLE_BYTES + 1 so an oversize body is detected
    // rather than silently truncated.
    let mut buffer = Vec::new();
    let body = response;
    body.take(MAX_BUNDLE_BYTES + 1)
        .read_to_end(&mut buffer)

View on GitHub (pinned to 73e0f67d83)