datawhalechina/hello-agents · error · RuntimeError
Semantic Scholar API 返回 HTTP {e.code}: {e.reason}
Error message
Semantic Scholar API 返回 HTTP {e.code}: {e.reason} What it means
RuntimeError raised when the Semantic Scholar API returns any non-429 HTTPError (e.g. 400 bad query, 401/403 invalid API key, 404 unknown endpoint, 5xx outage). The message interpolates the status code and reason: 'Semantic Scholar API returned HTTP {e.code}: {e.reason}'. Unlike 429, these errors are not retried — they propagate immediately.
Source
Thrown at Co-creation-projects/chengH425-PaperAssistant/src/literature_tool.py:216
with urllib.request.urlopen(req, timeout=20) as resp:
return json.loads(resp.read().decode("utf-8"))
except urllib.error.HTTPError as e:
if e.code == 429:
# 速率限制:等待后重试
wait = 2 ** (attempt + 1) # 2s, 4s, 8s
if attempt < max_retries - 1:
time.sleep(wait)
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(View on GitHub (pinned to 606a07d341)
Solutions
- Match the status: 400 → fix the request parameters; 401/403 → fix/regenerate the API key in .env; 5xx → retry later or check status.semanticscholar.org.
- Log the full request URL and query to see exactly what was sent when the 400 occurred.
- If 401/403 with a key set, confirm the key header name/value are correct (x-api-key) and not quoted in .env.
- Consider retrying 5xx responses with backoff the same way 429 is handled.
Example fix
// before
raise RuntimeError(
f"Semantic Scholar API returned HTTP {e.code}: {e.reason}"
) from e
# after
if 500 <= e.code < 600 and attempt < max_retries - 1:
time.sleep(2 ** (attempt + 1))
continue
raise RuntimeError(
f"Semantic Scholar API returned HTTP {e.code}: {e.reason}"
) from e Defensive patterns
Strategy: try-catch
Validate before calling
import os
def api_key_valid_format() -> bool:
key = os.getenv("SEMANTIC_SCHOLAR_API_KEY", "")
return key == "" or (key.isalnum() and len(key) >= 20) # heuristic; empty = anonymous tier Try / catch
import re
try:
data = _request(url)
except RuntimeError as e:
m = re.search(r"HTTP (\d+)", str(e))
code = int(m.group(1)) if m else 0
if code == 400:
fix_query_params() # non-retryable: bad request
elif 500 <= code < 600:
time.sleep(30); retry() # server-side, retryable later
elif code in (401, 403):
raise ConfigError("SEMANTIC_SCHOLAR_API_KEY invalid")
else:
raise Prevention
- URL-encode query parameters and validate them before sending.
- Keep the API key current; test it with a single curl call after rotation.
- Log request URL + status code on failure so 400s are diagnosable.
When it happens
Trigger: Passing a malformed or empty query parameter that the Graph API rejects with 400; setting `SEMANTIC_SCHOLAR_API_KEY` to an invalid/revoked value (401/403); hitting a temporary 5xx during API maintenance; using an outdated endpoint URL after an API version change.
Common situations: Typo'd or expired API key in .env, query strings containing unsupported operators or over-long inputs, Semantic Scholar infrastructure incidents.
Related errors
- API 请求频率已达上限(429 Too Many Requests)。\nSemantic Scholar 免费额度为
- 网络连接失败: {e.reason}
- 请求失败(已重试 {max_retries} 次): {last_error}
- 工具 '{tool_name}' 执行超时
- Hunter Agent执行失败: {str(e)}
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/bdb36bfedffb2ed5.
Report an issue: GitHub.