chenhg5/cc-connect · error

GitHub API returned HTTP %d

Error message

GitHub API returned HTTP %d

What it means

fetchLatestPreRelease returns this when the GitHub releases API responds with a status code other than 200. The code is embedded in the message so the developer can see exactly what GitHub returned (403 rate limit, 404 wrong repo, 5xx outage, etc.).

Source

Thrown at cmd/cc-connect/update.go:229

		return fetchLatestPreRelease()
	}
	return fetchLatestStableRelease()
}

// fetchLatestPreRelease fetches the newest release (including pre-releases) from GitHub.
func fetchLatestPreRelease() (*githubRelease, error) {
	client := &http.Client{Timeout: 15 * time.Second}
	req, _ := http.NewRequest("GET", githubAllAPI+"?per_page=10", nil)
	req.Header.Set("Accept", "application/vnd.github.v3+json")

	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("GitHub API returned HTTP %d", resp.StatusCode)
	}

	var releases []githubRelease
	if err := json.NewDecoder(resp.Body).Decode(&releases); err != nil {
		return nil, fmt.Errorf("parse releases: %w", err)
	}

	if len(releases) == 0 {
		return nil, fmt.Errorf("no releases found")
	}

	// Return the first (newest) release, which may be a pre-release
	return &releases[0], nil
}

// fetchLatestStableRelease fetches the latest stable release (no pre-releases).
func fetchLatestStableRelease() (*githubRelease, error) {
	client := &http.Client{Timeout: 15 * time.Second}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Read the exact HTTP code in the message; for 403 check X-RateLimit-Remaining — if 0, wait for reset or authenticate with a GITHUB_TOKEN header
  2. Verify githubAllAPI points at the correct repo (curl it directly and inspect the response)
  3. Check https://www.githubstatus.com for ongoing GitHub API incidents
  4. If a proxy/captive portal is present, exclude api.github.com or authenticate properly

Example fix

// before
req, _ := http.NewRequest("GET", githubAllAPI+"?per_page=10", nil)
// after
req, _ := http.NewRequest("GET", githubAllAPI+"?per_page=10", nil)
if tok := os.Getenv("GITHUB_TOKEN"); tok != "" {
    req.Header.Set("Authorization", "Bearer "+tok) // avoids 403 rate limits
}
Defensive patterns

Strategy: fallback

Validate before calling

// pre-check rate limit without consuming it:
req, _ := http.NewRequest("GET", "https://api.github.com/rate_limit", nil)
resp, err := http.DefaultClient.Do(req)
if err == nil {
    var r struct{ Resources struct{ Core struct{ Remaining int } } }
    json.NewDecoder(resp.Body).Decode(&r)
    if r.Resources.Core.Remaining == 0 { return errors.New("GitHub rate limit exhausted; set GITHUB_TOKEN") }
}

Try / catch

// Go: distinguish status classes
if _, err := fetchRelease(); err != nil {
    switch {
    case strings.Contains(err.Error(), "HTTP 403"):
        // rate limited: back off or authenticate
    case strings.Contains(err.Error(), "HTTP 404"):
        // wrong repo slug: fix githubAllAPI
    case strings.Contains(err.Error(), "HTTP 5"):
        // GitHub outage: retry later
    }
}

Prevention

When it happens

Trigger: The GET to githubAllAPI+"?per_page=10" succeeds at transport level but resp.StatusCode != 200: GitHub API rate limiting (HTTP 403, X-RateLimit-Remaining: 0), wrong repo slug producing 404, GitHub 5xx incidents, or an intercepting proxy returning an error page.

Common situations: Unauthenticated GitHub API calls from shared/CI IPs exhausting the 60 req/hour rate limit; typo in the repo slug baked into githubAllAPI; GitHub status incidents; captive portals or corporate middleware returning non-200.

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 chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/265694310f169e9b. Report an issue: GitHub.