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 assetView on GitHub (pinned to 329838acdf)
Solutions
- Set a GitHub token: `export GITHUB_TOKEN=ghp_...` (GH_TOKEN also works) to raise the limit to 5000 req/hour.
- Wait until the rate-limit window resets (check `curl -s https://api.github.com/rate_limit` for the reset time) and retry.
- Avoid polling in loops/scripts; cache the last check result and only query every few hours.
- 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
- Always export GITHUB_TOKEN or GH_TOKEN when scripting update checks
- Cache the latest-release result and check at most every few hours
- Don't run update checks in tight loops or parallel jobs sharing an IP
- Monitor X-RateLimit-Remaining if you call the API yourself
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
- GitHub API returned HTTP %d for %s
- 'ipfs id' cannot query information on remote peers without a
- no release found with a binary for %s/%s
- download returned HTTP %d
- downloading checksum file: %w
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/e48e2da80288833c.
Report an issue: GitHub.