666ghj/MiroFish · error · StarHistoryError
GitHub GraphQL request timed out
Error message
GitHub GraphQL request timed out
What it means
Raised when the `gh api graphql` subprocess exceeds its 45-second timeout (subprocess.TimeoutExpired). The GraphQL pagination request for 100 stargazers with starredAt normally completes in 1-3 s; hitting 45 s means gh is hung on network, auth re-prompting, or GitHub is slow.
Source
Thrown at scripts/star_history.py:208
def now(self) -> datetime:
return datetime.now(UTC).replace(microsecond=0)
class SubprocessCommandRunner:
def run(self, arguments: Sequence[str]) -> subprocess.CompletedProcess[str]:
try:
return subprocess.run(
list(arguments),
check=False,
capture_output=True,
text=True,
encoding="utf-8",
timeout=45,
)
except FileNotFoundError as exc:
raise StarHistoryError("GitHub CLI (gh) is required for backfill") from exc
except subprocess.TimeoutExpired as exc:
raise StarHistoryError("GitHub GraphQL request timed out") from exc
class GhGraphQLGateway:
"""Production adapter for the one-time, maintainer-authorized backfill."""
def __init__(self, runner: CommandRunner | None = None) -> None:
self._runner = runner or SubprocessCommandRunner()
def fetch_stargazer_page(self, after: str | None) -> StargazerPage:
arguments = [
"gh",
"api",
"graphql",
"-f",
f"query={GRAPHQL_QUERY}",
"-f",
f"owner={REPOSITORY_OWNER}",
"-f",View on GitHub (pinned to b5b53acc57)
Solutions
- Ensure non-interactive credentials: export GH_TOKEN (or GITHUB_TOKEN) before running backfill so gh never prompts.
- Retry the backfill command — it pages through cursors, so a single stall aborts the run; re-running resumes from persisted state.
- Check GitHub status and network latency to api.github.com; if consistently slow, raise the timeout in SubprocessCommandRunner.run from 45 s for this environment.
Example fix
# before: gh may block waiting for interactive auth
subprocess.run(["gh", "api", "graphql", ...], timeout=45)
# after: guarantee non-interactive auth
env = {**os.environ, "GH_TOKEN": os.environ["GH_TOKEN"]} # asserted present
subprocess.run(["gh", "api", "graphql", ...], timeout=45, env=env) Defensive patterns
Strategy: retry
Validate before calling
import os, shutil
# preflight: gh present and non-interactive credentials available
assert shutil.which("gh"), "gh not on PATH"
assert os.environ.get("GH_TOKEN") or os.environ.get("GITHUB_TOKEN"), (
"set GH_TOKEN so gh never blocks on interactive auth (45 s timeout)"
) Try / catch
for attempt in range(2):
try:
run_backfill()
break
except StarHistoryError as exc:
if "timed out" not in str(exc):
raise
time.sleep(10)
else:
raise SystemExit("gh graphql timed out twice; check network and GH_TOKEN") Prevention
- Always export GH_TOKEN/GITHUB_TOKEN in CI so gh never waits on a TTY prompt.
- Backfill is restartable — on timeout, re-run and let it resume from persisted state.
- Check `gh api rate_limit` before long backfills to avoid stalling against exhausted quotas.
When it happens
Trigger: gh attempting interactive auth or waiting on a locked keychain because GH_TOKEN is absent; severely throttled network egress; a stargazer page request stalling against GitHub during an incident; gh waiting on an auth token refresh that needs a TTY.
Common situations: CI without GH_TOKEN/GITHUB_TOKEN where gh blocks on re-auth prompts; proxied networks adding latency; GitHub GraphQL API degradation; oversized PAGE_SIZE interacting with a slow GraphQL backend.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- GitHub CLI (gh) is required for backfill
- GitHub GraphQL request failed (exit {completed.returncode})
- GitHub GraphQL returned malformed JSON
- 等待命令响应超时 ({timeout}秒)
- Zep batch {submission.batch_id} did not finish within {timeo
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/9d3b95ce8677223e.
Report an issue: GitHub.