astrid-runtime/astrid · error

GitHub API error querying release tag {candidate} for {org}/

Error message

GitHub API error querying release tag {candidate} for {org}/{repo}: HTTP {}

What it means

resolve_github_ref queries the GitHub API for a release with the requested tag. Any non-success, non-404 HTTP status (404 is treated as 'try next candidate') aborts resolution with this error, because the CLI cannot determine whether the pinned version exists.

Source

Thrown at crates/astrid-cli/src/commands/capsule/install_github.rs:68

    org: &str,
    repo: &str,
    version: Option<&str>,
    tag: Option<&str>,
) -> anyhow::Result<String> {
    if let Some(tag) = tag {
        return Ok(tag.to_string());
    }
    if let Some(version) = version {
        for candidate in [format!("v{version}"), version.to_string()] {
            let tag_url = release_tag_url(org, repo, &candidate)?;
            let response = client.get(&tag_url).send().await.with_context(|| {
                format!("failed to query release tag {candidate} for {org}/{repo}")
            })?;
            if response.status() == reqwest::StatusCode::NOT_FOUND {
                continue;
            }
            if !response.status().is_success() {
                bail!(
                    "GitHub API error querying release tag {candidate} for {org}/{repo}: HTTP {}",
                    response.status()
                );
            }
            let json = response
                .json::<serde_json::Value>()
                .await
                .with_context(|| format!("invalid GitHub API response for tag {candidate}"))?;
            return Ok(json
                .get("tag_name")
                .and_then(serde_json::Value::as_str)
                .unwrap_or(&candidate)
                .to_string());
        }
        bail!("no GitHub release found for version {version} in {org}/{repo}");
    }

    tracing::debug!(%org, %repo, "no version/tag pin — resolving latest release");

View on GitHub (pinned to affd8760f4)

Solutions

  1. Retry after waiting if the status is 403/429 — likely GitHub API rate limiting; set GITHUB_TOKEN to raise the limit.
  2. Check https://www.githubstatus.com for GitHub API incidents if you see 5xx.
  3. Verify the repo is public or provide credentials for a private repo (403).
  4. Check network/proxy configuration that might intercept api.github.com requests.

Example fix

// before (unauthenticated, rate-limited)
astrid capsule install github:org/repo@1.2.0
// after (authenticated, higher rate limit)
export GITHUB_TOKEN=ghp_...
astrid capsule install github:org/repo@1.2.0
Defensive patterns

Strategy: retry

Try / catch

// retry transient GitHub failures with backoff
for attempt in 0..3 {
    match install_capsule_from_github("org", "repo", Some("1.2.0")).await {
        Ok(_) => break,
        Err(e) if e.to_string().contains("GitHub API error") && attempt < 2 => {
            tokio::time::sleep(std::time::Duration::from_secs(2u64.pow(attempt))).await;
        }
        Err(e) => return Err(e),
    }
}

Prevention

When it happens

Trigger: install_from_github or resolve_capsule_to_file calls resolve_github_ref with a version pin; the GET to api.github.com/repos/{org}/{repo}/releases/tags/{candidate} returns a 4xx/5xx status other than NOT_FOUND.

Common situations: GitHub API rate limiting (403/429) from an unauthenticated client; a GitHub outage (5xx); a private repo returning 403 for an unauthenticated request; corporate proxy blocking api.github.com.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/a6d2b149def21f33. Report an issue: GitHub.