{"record":{"id":"a27dc3123a2bc3c0","repo":"Hmbown/CodeWhale","slug":"bundle-redirect-is-missing-a-valid-location-header","errorCode":null,"errorMessage":"bundle redirect is missing a valid Location header","messagePattern":"bundle redirect is missing a valid Location header","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/config_bundles.rs","lineNumber":783,"sourceCode":"    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 {}\",\n            response.status().as_u16()\n        );\n    }\n\n    // Read at most MAX_BUNDLE_BYTES + 1 so an oversize body is detected","sourceCodeStart":765,"sourceCodeEnd":801,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/config_bundles.rs#L765-L801","documentation":"During redirect handling in fetch_bundle, the server responded with a redirection status but sent no Location header at all. The client requires a Location header to know where to follow; a redirect without one is unusable, so it fails with this message. This is treated as an invalid server response rather than retrying.","triggerScenarios":"A 3xx response with no Location header (or a Location header containing non-ASCII/invalid bytes that fail to_str) while fetching a config bundle URL.","commonSituations":"Misconfigured reverse proxies emitting bare 302s, custom servers that redirect without Location, broken redirector scripts on bundle mirrors.","solutions":["Fix the server/proxy to include a Location header on redirect responses.","Fetch the final bundle URL directly instead of relying on the redirect.","Check for middleware or CDN rewriting the response and stripping Location.","Inspect the raw response with curl -i to confirm the malformed redirect."],"exampleFix":"// before (server)\nHTTP/1.1 302 Found\n\n// after (server)\nHTTP/1.1 302 Found\nLocation: https://host/bundle.toml","handlingStrategy":"fallback","validationCode":"let resp = client.get(url).send()?; if resp.status().is_redirection() && resp.headers().get(header::LOCATION).is_none() { eprintln!(\"malformed redirect from {}\", host); }","typeGuard":null,"tryCatchPattern":"if let Err(e) = fetch_bundle(url) { if e.to_string().contains(\"missing a valid Location\") { eprintln!(\"server sent redirect without Location; use direct URL\"); } }","preventionTips":["Point imports at final URLs, not redirectors.","Test mirror redirects with curl -i.","Fix reverse proxies to emit Location on 3xx."],"tags":["http","redirect","config-bundles"],"backgroundTag":"unexpected-response-shape","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"}