datawhalechina/hello-agents · error · MovieServiceError
TMDB 网络错误: {e}
Error message
TMDB 网络错误: {e} What it means
MovieServiceError raised when the httpx GET raises httpx.HTTPError that is not a TimeoutException — i.e. connection-level failures: DNS resolution errors (ConnectError wrapping socket.gaierror), TLS certificate failures, connection refused/reset, or protocol errors. Note the ordering matters: TimeoutException is a subclass scenario handled first, so this branch catches the remaining transport errors.
Source
Thrown at Co-creation-projects/aatanxiao12-beep-YingQian/backend/app/services/movie_service.py:120
else:
params["api_key"] = api_key # type: ignore[assignment]
return headers, params
def _get(self, path: str, extra_params: Optional[Dict[str, Any]] = None) -> dict:
"""对 TMDB 发 GET,统一处理超时、网络错误与非 2xx / 非 JSON。"""
headers, params = self._auth_headers_and_params()
if extra_params:
for k, v in extra_params.items():
if v is not None and v != "":
params[k] = v
url = f"{TMDB_API_BASE}{path}"
try:
resp = self._client.get(url, headers=headers, params=params)
except httpx.TimeoutException as e:
raise MovieServiceError(f"TMDB 请求超时: {e}") from e
except httpx.HTTPError as e:
raise MovieServiceError(f"TMDB 网络错误: {e}") from e
if resp.status_code == 401:
raise MovieServiceError(
"TMDB 鉴权失败:请检查 Access Token / API Key",
status_code=401,
)
if resp.status_code == 404:
raise MovieServiceError("影片不存在或已下架", status_code=404)
if resp.status_code >= 400:
raise MovieServiceError(
f"TMDB 请求失败: HTTP {resp.status_code}, {resp.text[:200]}"
)
try:
return resp.json()
except ValueError as e:
raise MovieServiceError("TMDB 返回非 JSON") from e
View on GitHub (pinned to 606a07d341)
Solutions
- Verify basic reachability: curl -I https://api.themoviedb.org/3/configuration from the same host/container
- Unset or fix proxy env vars (HTTP_PROXY/HTTPS_PROXY/ALL_PROXY) if they point at a dead proxy; or configure trust_env=False
- For TLS interception, provide the corporate CA bundle: httpx.Client(verify='/path/to/ca.pem')
- Distinguish DNS vs TLS vs refused in the message by including type(e).__name__
Example fix
# before
except httpx.HTTPError as e:
raise MovieServiceError(f"TMDB 网络错误: {e}") from e
# after
except httpx.ConnectError as e:
raise MovieServiceError(
f"TMDB 连接失败(DNS/网络不可达): {type(e).__name__}: {e}",
status_code=502,
) from e
except httpx.HTTPError as e:
raise MovieServiceError(f"TMDB 网络错误: {e}") from e Defensive patterns
Strategy: retry
Validate before calling
# preflight reachability (cheap TCP/DNS check, not per-request)
import socket
def tmdb_reachable(host: str = 'api.themoviedb.org') -> bool:
try:
socket.getaddrinfo(host, 443)
return True
except socket.gaierror:
return False Try / catch
except MovieServiceError as e:
if '网络错误' in str(e):
# transport-level: one retry, then degrade
return fallback_cache_or_empty()
raise Prevention
- Verify DNS/proxy env in the deployment (curl the API base from the same container)
- Provide corporate CA bundle to httpx(verify=...) when behind TLS inspection
- Separate ConnectError (config/network) from other HTTPError — only the latter is usually worth retrying
When it happens
Trigger: No internet or DNS failure resolving api.themoviedb.org; TLS interception proxy presenting an untrusted certificate (SSLError); connection reset by firewall/GFW-style filtering; proxy misconfiguration (httpx honors HTTP_PROXY env vars, and a dead proxy yields ConnectError); IPv6-only environment where TMDB is unreachable.
Common situations: Laptop on captive-portal Wi-Fi; corporate TLS-inspection with a custom CA not in certifi's bundle; HTTP_PROXY set in the environment pointing to a stopped local proxy; cloud egress blocked by security group.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/38c5bba6cf233574.
Report an issue: GitHub.