ipfs/kubo · error

GitHub API returned HTTP %d for %s

Error message

GitHub API returned HTTP %d for %s

What it means

githubGet returns `GitHub API returned HTTP %d for %s` for any non-200 response from the GitHub API that is not the rate-limit 403/429 case, including the URL that failed. It is a generic upstream HTTP failure wrapper so the developer can see the status code and endpoint.

Source

Thrown at core/commands/update_github.go:102

	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusTooManyRequests {
		resp.Body.Close()
		hint := ""
		if githubToken() == "" {
			hint = " (hint: set GITHUB_TOKEN or GH_TOKEN to avoid rate limits)"
		}
		return nil, fmt.Errorf("GitHub API rate limit exceeded%s", hint)
	}

	if resp.StatusCode != http.StatusOK {
		resp.Body.Close()
		return nil, fmt.Errorf("GitHub API returned HTTP %d for %s", resp.StatusCode, url)
	}

	return resp, nil
}

func githubToken() string {
	if t := os.Getenv("GITHUB_TOKEN"); t != "" {
		return t
	}
	return os.Getenv("GH_TOKEN")
}

// githubLatestRelease returns the newest release that has a platform asset
// for the current GOOS/GOARCH. This avoids false positives when a release
// tag exists but artifacts haven't been uploaded yet.
func githubLatestRelease(ctx context.Context, includePre bool) (*ghRelease, error) {
	releases, err := githubListReleases(ctx, 10, includePre)
	if err != nil {

View on GitHub (pinned to 329838acdf)

Solutions

  1. Read the status code in the message: 404 means the tag/release URL is wrong — verify the tag exists (`gh release view <tag>` or the releases page).
  2. 401: refresh/replace an invalid GITHUB_TOKEN; unset it entirely if you intended anonymous access.
  3. 5xx: check https://www.githubstatus.com and retry with backoff after the outage.
  4. If behind a corporate proxy, fix proxy env vars (HTTPS_PROXY) so api.github.com is reachable, and retry.

Example fix

// before
resp, err := githubGet(ctx, "https://api.github.com/repos/ipfs/kubo/releases/tags/"+tag) // tag="v9.9.9" -> 404
// after
tag, err := githubLatestTag(ctx) // discover a valid tag first
if err != nil { return err }
resp, err := githubGet(ctx, "https://api.github.com/repos/ipfs/kubo/releases/tags/"+tag)
Defensive patterns

Strategy: try-catch

Validate before calling

// verify tag exists before fetching its release
tags, _, err := ghClient.Repositories.ListTags(ctx, "ipfs", "kubo", nil)
if err != nil || !slices.ContainsFunc(tags, func(t *github.RepositoryTag) bool { return t.GetName() == tag }) {
	return fmt.Errorf("tag %q not found in ipfs/kubo", tag)
}

Try / catch

resp, err := githubGet(ctx, url)
if err != nil {
	var httpErr string
	if strings.Contains(err.Error(), "GitHub API returned HTTP ") {
		_, code, _ := strings.Cut(err.Error(), "HTTP ")
		switch code[:3] {
		case "404": return fmt.Errorf("release/tag not found")
		case "401": return fmt.Errorf("invalid GitHub token")
		default: return fmt.Errorf("github outage or proxy error, retry later: %w", err)
		}
	}
	return err
}

Prevention

When it happens

Trigger: githubListReleases or githubReleaseByTag hitting api.github.com and receiving 404 (bad tag/org/repo), 401 (invalid/expired token), 5xx (GitHub outage), or any other unexpected status like 410.

Common situations: Requesting a release tag that was deleted or renamed, an expired/revoked GITHUB_TOKEN, a typo'd repo/tag in code or tests, GitHub incident downtime, or an intercepting corporate proxy returning error pages.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/b3463a6121d2838e. Report an issue: GitHub.