{"record":{"id":"c1b484dcdac02b35","repo":"Hmbown/CodeWhale","slug":"release-redirect-did-not-resolve-to-a-tag-url-fi","errorCode":null,"errorMessage":"release redirect did not resolve to a tag URL: {final_url}","messagePattern":"release redirect did not resolve to a tag URL: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/update.rs","lineNumber":1508,"sourceCode":"    url: &str,\n) -> Result<String> {\n    let response = client\n        .get(url)\n        .send()\n        .with_context(|| format!(\"failed to fetch release redirect from {url}\"))?;\n    let status = response.status();\n    let final_url = response.url().clone();\n    if status.is_success() {\n        if let Some(tag_name) = release_tag_from_github_release_url(&final_url) {\n            return Ok(tag_name);\n        }\n        let body = response\n            .text()\n            .with_context(|| format!(\"failed to read release redirect response from {url}\"))?;\n        if let Some(tag_name) = release_tag_from_github_release_html(&body) {\n            return Ok(tag_name);\n        }\n        bail!(\"release redirect did not resolve to a tag URL: {final_url}\");\n    }\n\n    let body = response\n        .text()\n        .with_context(|| format!(\"failed to read release redirect response from {url}\"))?;\n    bail!(\"failed to fetch release redirect from {url}: HTTP {status}\\n{body}\");\n}\n\nfn release_tag_from_github_release_url(url: &reqwest::Url) -> Option<String> {\n    let segments = url.path_segments()?.collect::<Vec<_>>();\n    segments\n        .windows(3)\n        .find(|window| window[0] == \"releases\" && window[1] == \"tag\")\n        .map(|window| window[2].to_string())\n        .filter(|tag| !tag.is_empty())\n}\n\nfn release_tag_from_github_release_html(body: &str) -> Option<String> {","sourceCodeStart":1490,"sourceCodeEnd":1526,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/update.rs#L1490-L1526","documentation":"Thrown when resolving the latest release via a GitHub redirect. The updater follows the '/releases/latest' redirect, reads the final HTML, and extracts the tag name; if the HTML does not contain a recognizable release tag URL, it cannot determine which version to update to and fails.","triggerScenarios":"Self-update fetches the release redirect page, response is 200 but release_tag_from_github_release_html() finds no tag URL in the body (e.g. login page, org page, or consent/captcha HTML returned instead of a release page).","commonSituations":"Corporate proxy or firewall rewriting the GitHub response; GitHub serving an interstitial/error page; the release URL scheme changed; hitting a mirror that does not preserve the /tag/<name> URL structure.","solutions":["Check network path for proxies/rewriting and retry from a direct connection.","Inspect final_url in the message to see where the redirect actually landed.","Update manually by downloading the release from GitHub instead of self-update.","Retry later if GitHub was serving an error/interstitial page."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"match updater::resolve_latest_tag() {\n    Ok(tag) => tag,\n    Err(e) if e.to_string().contains(\"did not resolve to a tag URL\") => {\n        eprintln!(\"redirect page unrecognized ({e}); falling back to manual download\");\n        manual_update_fallback()?  // or: parse the GitHub releases API instead\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Check the final URL in the error to detect proxy/interstitial rewriting.","Query the GitHub releases API endpoint as a structured alternative to HTML scraping.","Avoid corporate proxies that rewrite GitHub responses, or allowlist github.com.","Retry after transient GitHub incidents before assuming a code bug."],"tags":["update","github","redirect","network"],"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-23T08:17:48.524Z"}