Hmbown/CodeWhale · error

release redirect did not resolve to a tag URL

Error message

release redirect did not resolve to a tag URL: {final_url}

What it means

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.

Solutions

  1. Check network path for proxies/rewriting and retry from a direct connection.
  2. Inspect final_url in the message to see where the redirect actually landed.
  3. Update manually by downloading the release from GitHub instead of self-update.
  4. Retry later if GitHub was serving an error/interstitial page.
Defensive patterns

Strategy: fallback

Try / catch

match updater::resolve_latest_tag() {
    Ok(tag) => tag,
    Err(e) if e.to_string().contains("did not resolve to a tag URL") => {
        eprintln!("redirect page unrecognized ({e}); falling back to manual download");
        manual_update_fallback()?  // or: parse the GitHub releases API instead
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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

Appendix: source

Thrown at crates/cli/src/update.rs:1508

    url: &str,
) -> Result<String> {
    let response = client
        .get(url)
        .send()
        .with_context(|| format!("failed to fetch release redirect from {url}"))?;
    let status = response.status();
    let final_url = response.url().clone();
    if status.is_success() {
        if let Some(tag_name) = release_tag_from_github_release_url(&final_url) {
            return Ok(tag_name);
        }
        let body = response
            .text()
            .with_context(|| format!("failed to read release redirect response from {url}"))?;
        if let Some(tag_name) = release_tag_from_github_release_html(&body) {
            return Ok(tag_name);
        }
        bail!("release redirect did not resolve to a tag URL: {final_url}");
    }

    let body = response
        .text()
        .with_context(|| format!("failed to read release redirect response from {url}"))?;
    bail!("failed to fetch release redirect from {url}: HTTP {status}\n{body}");
}

fn release_tag_from_github_release_url(url: &reqwest::Url) -> Option<String> {
    let segments = url.path_segments()?.collect::<Vec<_>>();
    segments
        .windows(3)
        .find(|window| window[0] == "releases" && window[1] == "tag")
        .map(|window| window[2].to_string())
        .filter(|tag| !tag.is_empty())
}

fn release_tag_from_github_release_html(body: &str) -> Option<String> {

View on GitHub (pinned to 73e0f67d83)