aaif-goose/goose · error

GitHub API returned ${response.status}: ${response.statusTex

Error message

GitHub API returned ${response.status}: ${response.statusText}

What it means

githubUpdater fetches the latest release from the GitHub releases API; any non-2xx response throws with the HTTP status and status text. The response body is logged before throwing. The two dominant causes are rate limiting (403 with X-RateLimit-Remaining: 0 for unauthenticated clients — 60 req/hour per IP) and a 404 because the configured owner/repo is wrong or the release is private without a token.

Source

Thrown at ui/desktop/src/utils/githubUpdater.ts:67

      const response = await fetch(this.apiUrl, {
        headers: {
          Accept: 'application/vnd.github.v3+json',
          'User-Agent': `Goose-Desktop/${app.getVersion()}`,
        },
        signal: controller.signal,
      });

      clearTimeout(timeoutId);
      const fetchDuration = Date.now() - startTime;
      log.info(
        `GitHubUpdater: GitHub API response status: ${response.status} ${response.statusText} (took ${fetchDuration}ms)`
      );

      if (!response.ok) {
        const errorText = await response.text();
        log.error(`GitHubUpdater: GitHub API error response: ${errorText}`);
        throw new Error(`GitHub API returned ${response.status}: ${response.statusText}`);
      }

      const release: GitHubRelease = await safeJsonParse<GitHubRelease>(
        response,
        'Failed to get GitHub release information'
      );
      log.info(`GitHubUpdater: Found release: ${release.tag_name} (${release.name})`);
      log.info(`GitHubUpdater: Release published at: ${release.published_at}`);
      log.info(`GitHubUpdater: Release assets count: ${release.assets.length}`);

      const latestVersion = release.tag_name.replace(/^v/, ''); // Remove 'v' prefix if present
      const currentVersion = app.getVersion();

      log.info(
        `GitHubUpdater: Current version: ${currentVersion}, Latest version: ${latestVersion}`
      );

      // Compare versions

View on GitHub (pinned to 3810898a74)

Solutions

  1. If 403: wait for the rate-limit window to reset (check X-RateLimit-Reset) or supply an authenticated request/GITHUB_TOKEN so the limit rises to 5000/h
  2. If 404: verify the owner/repo the updater queries and that the latest release exists and is public
  3. If 5xx: retry with backoff — GitHub API transient failures are common
  4. Cache release-check results to avoid re-querying on every launch

Example fix

// before
const response = await fetch(releaseApiUrl);
// after (fail fast on rate limit, keep body details)
const response = await fetch(releaseApiUrl);
if (response.status === 403 || response.status === 429) {
  const reset = response.headers.get('x-ratelimit-reset');
  log.warn(`Rate limited until ${reset}`);
}
Defensive patterns

Strategy: retry

Validate before calling

// Check rate-limit headers before treating failure as fatal:
const response = await fetch(apiUrl);
const remaining = Number(response.headers.get('x-ratelimit-remaining') ?? '1');
if (remaining <= 1) scheduleNextCheckAfterReset(response.headers.get('x-ratelimit-reset'));

Try / catch

async function checkWithBackoff(retries = 3): Promise<GitHubRelease> {
  for (let i = 0; i <= retries; i++) {
    try {
      return await checkLatestRelease();
    } catch (e) {
      const s = String(e);
      const rateLimited = s.includes(' 403') || s.includes(' 429');
      if (i === retries || (rateLimited && !hasToken)) throw e;
      await new Promise(r => setTimeout(r, 2 ** i * 1000));
    }
  }
  throw new Error('unreachable');
}

Prevention

When it happens

Trigger: checkForUpdates via GitHub fallback after electron-updater failed; more than 60 unauthenticated API calls/hour (shared NAT IPs amplify this); wrong GITHUB owner/repo in updater config; private repo fetched without authorization; GitHub incident returning 5xx.

Common situations: Corporate NAT pooling many users behind one IP; misconfigured repo after a rename/transfer; CI runs hammering the API; release not yet published when the client checks.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/664ad38f3f4cbead. Report an issue: GitHub.