maboloshi/github-chinese · error · RuntimeError

请求失败(重试 {retries} 次后仍失败):{last_err}

Error message

请求失败(重试 {retries} 次后仍失败):{last_err}

What it means

fetch() is the script's shared HTTP getter with bounded exponential backoff (time.sleep(2*(attempt+1))) over retries attempts (default 3). It only reaches the final raise for 5xx responses or network-layer exceptions (URLError/timeout/SSL) that survive all retries; 4xx (including 401/403/404/429) are re-raised immediately as urllib.error.HTTPError and never produce this RuntimeError. The message reports the last failure reason but, notably, not the URL that failed.

Source

Thrown at script/ai_review.py:38

def fetch(url: str, headers: dict | None = None, retries: int = 3) -> str:
    """拉取 URL;对 5xx / 网络错误做指数退避重试。"""
    req = urllib.request.Request(
        url, headers=headers or {"User-Agent": "github-chinese-ai-review"}
    )
    last_err = ""
    for attempt in range(retries):
        try:
            with urllib.request.urlopen(req, timeout=60) as r:
                return r.read().decode("utf-8")
        except urllib.error.HTTPError as e:
            last_err = f"HTTP {e.code}"
            if e.code < 500:  # 4xx 不重试
                raise
        except Exception as e:  # noqa: BLE001 - 网络层异常统一重试
            last_err = str(e)
        time.sleep(2 * (attempt + 1))
    raise RuntimeError(f"请求失败(重试 {retries} 次后仍失败):{last_err}")


def main() -> None:
    parser = argparse.ArgumentParser(description="AI 代码审查(DeepSeek)")
    parser.add_argument("--repo", required=True, help="owner/repo")
    parser.add_argument("--pr", required=True, help="PR 编号")
    parser.add_argument("--mode", choices=["full", "summary"], default="full")
    parser.add_argument("--out", help="输出文件(默认 stdout)")
    args = parser.parse_args()

    api_key = os.environ.get("LLM_API_KEY")
    if not api_key:
        print("❌ 缺少环境变量 LLM_API_KEY", file=sys.stderr)
        sys.exit(1)

    # 1) PR 元数据 + diff
    try:
        pr_meta = json.loads(fetch(f"https://api.github.com/repos/{args.repo}/pulls/{args.pr}"))

View on GitHub (pinned to 1db777260a)

Solutions

  1. Retry after a short wait — 5xx and transient network errors often clear; rerun the script once connectivity is stable.
  2. Verify network/proxy: ensure HTTPS_PROXY is set if behind a firewall and that api.github.com resolves (DNS) and TLS completes.
  3. Increase resilience by raising retries and/or the per-request timeout for the github.com diff endpoint, which can be slow on large PRs.
  4. If hitting GitHub auth limits, supply a token header to lift the 60/hr anonymous cap (note: 403/429 surface as HTTPError, not this RuntimeError).

Example fix

# before
    raise RuntimeError(f"请求失败(重试 {retries} 次后仍失败):{last_err}")
# after — include the URL and status so the caller knows which call failed
    raise RuntimeError(f"请求失败(重试 {retries} 次后仍失败):{url} → {last_err}")
Defensive patterns

Strategy: retry

Validate before calling

# Before calling fetch(), confirm connectivity to the target host:
import socket
for host in ("api.github.com", "github.com"):
    try:
        socket.gethostbyname(host)
    except OSError as e:
        sys.exit(f"❌ 无法解析 {host},请检查 DNS/代理:{e}")

Type guard

null

Try / catch

try:
    pr_meta = json.loads(fetch(url, retries=3))
except (RuntimeError, urllib.error.HTTPError) as e:
    print(f"❌ PR 拉取失败:{e}", file=sys.stderr)
    sys.exit(1)

Prevention

When it happens

Trigger: Calling fetch() against api.github.com (PR metadata), github.com (.../pull/N.diff), raw.githubusercontent.com (copilot-instructions.md), and hitting a sustained 5xx from those hosts — or a connection error (DNS, TLS, proxy, read timeout >60s) — for all 3 attempts. Each caller (main()) wraps fetch in its own try/except and exits with a tailored message, so this RuntimeError is the inner cause printed there.

Common situations: api.github.com or github.com briefly 5xx-ing; a flaky proxy or VPN dropping mid-request; an aggressive firewall resetting TLS; GitHub rate-limiting returning 429 (re-raised as HTTPError before exhaustion, so not this message); running the script where LLM_BASE_URL/HTTPS_PROXY is mis-set.

Related errors


AI-assisted analysis of maboloshi/github-chinese@1db777260a (2026-08-13). Data as JSON: /api/errors/cd63dca27f54985e. Report an issue: GitHub.