datawhalechina/hello-agents · error · RuntimeError

请求失败(已重试 {max_retries} 次): {last_error}

Error message

请求失败(已重试 {max_retries} 次): {last_error}

What it means

The final fall-through RuntimeError in the Semantic Scholar request loop: it fires only if the for-loop completes without returning or raising, carrying the last URLError observed. Message: 'request failed (retried {max_retries} times): {last_error}'. It is a defensive exhaust-path covering transient network errors that survived all retries.

Source

Thrown at Co-creation-projects/chengH425-PaperAssistant/src/literature_tool.py:226

                        continue
                    raise RuntimeError(
                        "API 请求频率已达上限(429 Too Many Requests)。\n"
                        "Semantic Scholar 免费额度为 100 次/5 分钟。\n"
                        "请稍等 1-5 分钟后重试,或申请免费 API Key:\n"
                        "https://www.semanticscholar.org/product/api\n"
                        "获取后在 .env 中设置 SEMANTIC_SCHOLAR_API_KEY"
                    ) from e
                raise RuntimeError(
                    f"Semantic Scholar API 返回 HTTP {e.code}: {e.reason}"
                ) from e
            except urllib.error.URLError as e:
                last_error = e
                if attempt < max_retries - 1:
                    time.sleep(2 ** (attempt + 1))
                    continue
                raise RuntimeError(f"网络连接失败: {str(e.reason)}") from e

        raise RuntimeError(f"请求失败(已重试 {max_retries} 次): {last_error}")

    def run(self, parameters: Dict[str, Any]) -> ToolResponse:
        keyword = parameters.get("keyword", "")
        author = parameters.get("author", "")
        field = parameters.get("field", "")

        if not keyword and not author:
            return ToolResponse.error(
                code="INVALID_PARAM",
                message="请至少提供关键词(keyword)或作者(author)"
            )

        url = self._build_url(parameters)
        api_key = os.getenv("SEMANTIC_SCHOLAR_API_KEY", "")

        try:
            data = self._make_request(url, api_key)

View on GitHub (pinned to 606a07d341)

Solutions

  1. Inspect `{last_error}` in the message — it names the actual network failure to fix (DNS, refused, timeout).
  2. Stabilize connectivity or fix proxy settings, then retry the tool call.
  3. Increase max_retries/backoff if transient flakiness is expected in your environment.
  4. Treat as non-retryable at the caller level: the client already retried; immediate re-calls will likely fail too.
Defensive patterns

Strategy: retry

Try / catch

try:
    data = _request(url)
except RuntimeError as e:
    if "已重试" in str(e):
        # client already exhausted its retries with short backoff;
        # back off much longer before the next attempt
        time.sleep(120)
        data = _request(url)
    else:
        raise

Prevention

When it happens

Trigger: Every retry attempt raises URLError (persistent offline state, unreachable proxy) — each iteration sleeps and continues, and after the last attempt the loop exits to this raise. Note: per-attempt HTTPError paths raise earlier, so this line is reached mainly via the URLError branch.

Common situations: Extended network outages, misconfigured proxy that consistently fails, or flaky Wi-Fi where 2s/4s backoff is not enough for recovery.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/147f15b0d14d61cd. Report an issue: GitHub.