google-gemini/gemini-cli · error · RuntimeError
Failed to fetch issue #{issue_number} from GitHub API ({resp
Error message
Failed to fetch issue #{issue_number} from GitHub API ({resp.status_code}): {resp.text} What it means
This RuntimeError is raised by get_issue_details() when the GitHub REST API GET to /repos/{owner}/{repo}/issues/{issue_number} returns any non-200 HTTP status. The error includes the status code and raw response body so the caller can distinguish rate limits (403/429), auth failures (401), not-found (404), and server errors (5xx). It is a hard failure because the eval pipeline cannot proceed without issue data.
Source
Thrown at tools/caretaker-agent/evals/triage/helpers/github_api.py:29
def _get_github_headers() -> Dict[str, str]:
"""
Optionally retrieves GITHUB_TOKEN (or GH_TOKEN) to authenticate requests.
"""
token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
headers = {"Accept": "application/vnd.github.v3+json"}
if token:
headers["Authorization"] = f"Bearer {token}"
return headers
def get_issue_details(owner: str, repo: str, issue_number: int) -> Dict[str, Any]:
"""Queries GitHub REST API for issue details (title, body, createdAt, labels)."""
url = f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}"
resp = requests.get(url, headers=_get_github_headers(), timeout=15)
if resp.status_code != 200:
raise RuntimeError(f"Failed to fetch issue #{issue_number} from GitHub API ({resp.status_code}): {resp.text}")
data = resp.json()
return {
"owner": owner,
"repo": repo,
"number": data.get("number"),
"title": data.get("title", ""),
"body": data.get("body", "") or "",
"createdAt": data.get("created_at", ""),
"labels": data.get("labels", [])
}
def get_pr_details(owner: str, repo: str, pr_number: int) -> Dict[str, Any]:
"""Queries GitHub REST API for PR details (title, body, baseRefOid, patch/diff)."""
url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}"
headers = _get_github_headers()
resp = requests.get(url, headers=headers, timeout=15)View on GitHub (pinned to 5024443c72)
Solutions
- Set a valid GITHUB_TOKEN (or GH_TOKEN) env var with repo read scope and retry.
- Verify owner, repo, and issue_number are correct and that the issue exists at the URL in a browser.
- If status is 403/429, wait for the rate-limit window to reset (check X-RateLimit-Reset header) or reduce concurrency in the eval runner.
- Add a retry with exponential backoff around get_issue_details for transient 5xx responses.
- Confirm Cloud Run / network egress to api.github.com is permitted.
Example fix
# before
os.environ.pop('GITHUB_TOKEN', None) # anonymous, hits rate limit fast
# after
os.environ['GITHUB_TOKEN'] = 'ghp_...' # authenticated, 5000 req/hr Defensive patterns
Strategy: retry
Validate before calling
import os, requests
def can_fetch_issue(owner: str, repo: str, issue_number: int) -> bool:
headers = {'Accept': 'application/vnd.github.v3+json'}
token = os.environ.get('GITHUB_TOKEN') or os.environ.get('GH_TOKEN')
if token:
headers['Authorization'] = f'Bearer {token}'
resp = requests.get(f'https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}', headers=headers, timeout=15)
return resp.status_code == 200 Try / catch
import time
from evals.triage.helpers.github_api import get_issue_details
for attempt in range(3):
try:
issue = get_issue_details(owner, repo, issue_number)
break
except RuntimeError as e:
if '403' in str(e) or '429' in str(e):
time.sleep(2 ** attempt)
else:
raise
else:
raise RuntimeError(f'Could not fetch issue {issue_number} after retries') Prevention
- Set a valid GITHUB_TOKEN/GH_TOKEN with appropriate scope before running the eval.
- Respect X-RateLimit-Remaining and back off near the limit.
- Validate owner/repo/issue_number against the live API in a pre-flight check.
- Cache issue JSON locally to avoid refetching across eval runs.
When it happens
Trigger: Calling get_issue_details(owner, repo, issue_number) with a wrong owner/repo, an issue number that does not exist (404), no token when the repo is private (404/403), an expired/invalid GITHUB_TOKEN (401), or hitting a secondary rate limit (403 with 'rate limit' message, or 429). Network issues typically raise ConnectionError before this guard.
Common situations: GITHUB_TOKEN/GH_TOKEN is unset or expired and the eval tries to fetch a private-repo issue. A typo in owner or repo. The issue was deleted or is actually a PR (use the pulls endpoint). GitHub primary rate limit exhausted (5000 req/hr authenticated). Cloud Run egress blocked or DNS failing producing a non-200 from a proxy.
Related errors
- Failed to fetch PR #{pr_number} from GitHub API ({resp.statu
- Invalid response code downloading ${endpoint}: ${response.st
- No access token received from token endpoint
- GitHub token is missing. Cannot authorize Pull Request creat
- EVAL_CONFIG must be a JSON object, got {type(cfg).__name__}
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/eea4422357b54e16.
Report an issue: GitHub.