can1357/oh-my-pi · error · HTTPException

github error: {exc.status} {exc.message}

Error message

github error: {exc.status} {exc.message}

What it means

A GitHubError escaped the triage call and api_trigger converts it into HTTP 502 with the message 'github error: {status} {message}'. The server successfully received your request but its call to the GitHub API failed with HTTP status `exc.status` and message `exc.message`. This marks an upstream dependency failure rather than a problem with your request.

Source

Thrown at python/robomp/src/server.py:632

            try:
                repo_full, number = parse_issue_ref(issue_ref)
            except InvalidIssueRef as exc:
                raise HTTPException(400, str(exc)) from exc
            if not cfg.allows(repo_full):
                raise HTTPException(403, f"{repo_full} not in ROBOMP_REPO_ALLOWLIST")
            try:
                delivery = await enqueue_manual_triage(
                    db=db,
                    github=github,
                    repo_full=repo_full,
                    number=number,
                )
            except ManualTriageConflict as exc:
                raise HTTPException(409, str(exc)) from exc
            except ManualTriageError as exc:
                raise HTTPException(400, str(exc)) from exc
            except GitHubError as exc:
                raise HTTPException(502, f"github error: {exc.status} {exc.message}") from exc
            pool.wake()
            log.info("manual triage", extra={"delivery": delivery, "issue": f"{repo_full}#{number}"})
            return JSONResponse(
                {"delivery": delivery, "state": "queued", "mode": "triage"},
                status_code=202,
            )

        # mode == "retry"
        if isinstance(delivery_id, str) and delivery_id:
            target = delivery_id
        elif isinstance(issue_ref, str) and issue_ref:
            try:
                repo_full, number = parse_issue_ref(issue_ref)
            except InvalidIssueRef as exc:
                raise HTTPException(400, str(exc)) from exc
            if not cfg.allows(repo_full):
                raise HTTPException(403, f"{repo_full} not in ROBOMP_REPO_ALLOWLIST")
            row = db.latest_event_for_issue(make_issue_key(repo_full, number))

View on GitHub (pinned to 9690622007)

Solutions

  1. Read `exc.status` and `exc.message` from the 502 body — they mirror GitHub's own response and pinpoint the cause
  2. If 401/403: verify and refresh the GitHub token used by the server and confirm it has access to the target repo
  3. If 403 with rate-limit message: wait for the rate-limit window to reset or use a token with a higher quota
  4. If 404: confirm the repo exists and the token can see it (private repo membership)
  5. If 5xx: check GitHub status and retry the trigger once the upstream recovers

Example fix

// before: token from stale env
client = GitHub(token=os.environ['OLD_GH_TOKEN'])
// after: refreshed token with required scopes
client = GitHub(token=os.environ['GH_TOKEN'])  # updated secret, repo scope granted
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: verify the token can read the target repo before triggering triage
const check = await fetch(`https://api.github.com/repos/${repoFull}`, {
  headers: { Authorization: `Bearer ${ghToken}`, Accept: 'application/vnd.github+json' },
});
if (!check.ok) throw new Error(`GitHub pre-flight failed: ${check.status} ${await check.text()}`);

Type guard

function isGitHubErrorDetail(body: unknown): body is { detail: string } & { status: number } {
  return typeof body === 'object' && body !== null &&
    typeof (body as any).detail === 'string' && /^github error: \d{3} /.test((body as any).detail);
}

Try / catch

try {
  await api.trigger(payload);
} catch (err) {
  const m = /^github error: (\d{3}) /.exec(err.message ?? '');
  if (m) {
    const gh = Number(m[1]);
    if (gh === 403 && /rate limit/i.test(err.message)) await Bun.sleep(rateLimitResetMs);
    else if (gh >= 500) await Bun.sleep(retryMs); // transient GitHub outage
    else logger.error('GitHub rejected the server call', { gh, detail: err.message }); // 401/403/404: fix token/repo
  } else throw err;
}

Prevention

When it happens

Trigger: Any trigger request where the triage path performs GitHub API calls (fetching the issue, labels, permissions, or posting triage results) and GitHub responds with a non-OK status — 401/403 for bad or expired tokens, 404 for a repo the token cannot see, 422 for invalid API input, 403 with rate-limit headers when the token is exhausted.

Common situations: ROBOMP GitHub token expired or rotated without updating the server config; token lacking access to a private repo in the allowlist; hitting GitHub's rate limit during webhook storms; a branch/issue being deleted between triage queuing and execution; GitHub incidents/5xx outages.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/0874719833cf73c7. Report an issue: GitHub.