google-gemini/gemini-cli · error · RuntimeError
Failed to fetch PR #{pr_number} from GitHub API ({resp.statu
Error message
Failed to fetch PR #{pr_number} from GitHub API ({resp.status_code}): {resp.text} What it means
This RuntimeError is raised by get_pr_details() when the GitHub REST API GET to /repos/{owner}/{repo}/pulls/{pr_number} returns a non-200 status. The function fetches PR metadata first, then a separate diff request; this guard is on the metadata fetch. The error message surfaces the status code and body to diagnose auth, rate-limit, or not-found conditions.
Source
Thrown at tools/caretaker-agent/evals/triage/helpers/github_api.py:49
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)
if resp.status_code != 200:
raise RuntimeError(f"Failed to fetch PR #{pr_number} from GitHub API ({resp.status_code}): {resp.text}")
data = resp.json()
# Fetch unified patch/diff
diff_url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}"
diff_headers = headers.copy()
diff_headers["Accept"] = "application/vnd.github.v3.diff"
diff_resp = requests.get(diff_url, headers=diff_headers, timeout=15)
diff_content = diff_resp.text if diff_resp.status_code == 200 else ""
return {
"number": data.get("number"),
"title": data.get("title", ""),
"body": data.get("body", "") or "",
"baseRefOid": data.get("base", {}).get("sha", ""),
"diff": diff_content
}
View on GitHub (pinned to 5024443c72)
Solutions
- Confirm the PR exists: open https://github.com/{owner}/{repo}/pull/{pr_number} in a browser.
- Set/refresh GITHUB_TOKEN with repo scope for private repositories.
- If rate-limited (403/429), reduce concurrency or wait for X-RateLimit-Reset.
- Ensure you pass a PR number, not an issue number; use get_issue_details for issues.
- Add retry with backoff for 5xx transient failures.
Example fix
# before: passing an issue number where a PR is expected pr = get_pr_details(owner, repo, issue_number) # after: resolve the linked PR number first pr = get_pr_details(owner, repo, linked_pr_number)
Defensive patterns
Strategy: retry
Validate before calling
import os, requests
def can_fetch_pr(owner: str, repo: str, pr_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}/pulls/{pr_number}', headers=headers, timeout=15)
return resp.status_code == 200 Try / catch
import time
from evals.triage.helpers.github_api import get_pr_details
for attempt in range(3):
try:
pr = get_pr_details(owner, repo, pr_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 PR {pr_number} after retries') Prevention
- Confirm pr_number is a PR (not an issue) before calling get_pr_details.
- Set and refresh GITHUB_TOKEN with repo scope for private repos.
- Watch rate-limit headers and throttle concurrency accordingly.
- Cache PR JSON to avoid repeated fetches.
When it happens
Trigger: Calling get_pr_details(owner, repo, pr_number) with a non-existent PR number (404), an expired token (401), a rate-limited token (403/429), or a pr_number that is actually an issue (the pulls endpoint returns 404 for non-PRs). The owner/repo is private and no token is set.
Common situations: Confusing an issue number with a PR number. Token lacking repo scope for a private repo. GitHub rate limit exhausted after fetching many issues in a batch eval. Stale PR number after the PR was deleted or the repo renamed.
Related errors
- Failed to fetch issue #{issue_number} from GitHub API ({resp
- 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/893124e169d8216f.
Report an issue: GitHub.