ipfs/kubo · error

GitHub API rate limit exceeded%s

Error message

GitHub API rate limit exceeded%s

What it means

githubGet in core/commands/update_github.go treats HTTP 403 or 429 from api.github.com as a GitHub API rate-limit rejection and returns `GitHub API rate limit exceeded` plus a hint when no GITHUB_TOKEN/GH_TOKEN is set. Unauthenticated GitHub requests are limited to ~60/hour per IP, so anonymous update checks exhaust the quota quickly, especially behind shared NAT/CI IPs.

Source

Thrown at core/commands/update_github.go:97

	req.Header.Set("Accept", "application/vnd.github+json")
	req.Header.Set("User-Agent", "kubo/"+version.CurrentVersionNumber)

	if token := githubToken(); token != "" {
		req.Header.Set("Authorization", "Bearer "+token)
	}

	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

View on GitHub (pinned to 329838acdf)

Solutions

  1. Set a GitHub token: `export GITHUB_TOKEN=ghp_...` (GH_TOKEN also works) to raise the limit to 5000 req/hour.
  2. Wait until the rate-limit window resets (check `curl -s https://api.github.com/rate_limit` for the reset time) and retry.
  3. Avoid polling in loops/scripts; cache the last check result and only query every few hours.
  4. If on shared CI/VPN infrastructure, use a token or a different egress IP.

Example fix

// before
$ ipfs update check
Error: GitHub API rate limit exceeded (hint: set GITHUB_TOKEN or GH_TOKEN to avoid rate limits)
// after
$ export GITHUB_TOKEN=ghp_xxx   # or GH_TOKEN
$ ipfs update check
Defensive patterns

Strategy: retry

Validate before calling

// pre-check quota before calling update
resp, err := http.Get("https://api.github.com/rate_limit")
if err == nil {
	var rl struct{ Resources struct{ Core struct{ Remaining int; Reset int64 } } }
	json.NewDecoder(resp.Body).Decode(&rl)
	if rl.Resources.Core.Remaining == 0 {
		return fmt.Errorf("GitHub quota exhausted until %v", time.Unix(rl.Resources.Core.Reset, 0))
	}
}

Try / catch

rel, err := githubLatestRelease(ctx, false)
if err != nil {
	if strings.Contains(err.Error(), "rate limit exceeded") {
		// honor Retry-After style backoff, or surface the GITHUB_TOKEN hint
		time.Sleep(backoff)
		rel, err = githubLatestRelease(ctx, false)
	}
	if err != nil { return err }
}

Prevention

When it happens

Trigger: Calling `ipfs update check` / `ipfs update fetch` (via githubListReleases or githubReleaseByTag) more than ~60 times per hour from the same IP without a token; running in CI where the runner IP is shared; or a proxy/firewall returning 403 in a way GitHub surfaces as Forbidden.

Common situations: Repeated update checks in automation, a corporate/VPN exit IP already exhausted by others, Docker containers sharing the host IP, or simply forgetting to export GITHUB_TOKEN despite having one.

Related errors


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