datawhalechina/hello-agents · warning · MovieServiceError
影片不存在或已下架
Error message
影片不存在或已下架
What it means
MovieServiceError with status_code=404 raised when TMDB returns HTTP 404 — the requested movie id does not exist (never assigned, or beyond the id space) or the content is unavailable in the requested language/region market and TMDB serves 404 instead of an empty body. Because get_detail builds /movie/{movie_id}?append_to_response=credits, a movie whose credits endpoint 404s also surfaces here.
Source
Thrown at Co-creation-projects/aatanxiao12-beep-YingQian/backend/app/services/movie_service.py:128
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
def _poster_url(self, poster_path: Optional[str]) -> Optional[str]:
"""把 TMDB 相对 poster_path 拼成可访问的完整图片 URL。"""
if not poster_path:
return None
base = self.settings.tmdb_image_base_url.rstrip("/")
return f"{base}{poster_path}"
def _parse_year(self, release_date: Optional[str]) -> Optional[int]:View on GitHub (pinned to 606a07d341)
Solutions
- Resolve ids via search/discover first instead of trusting raw ids, then call get_detail on the returned result
- Map external ids properly: use /find/{external_id}?external_source=imdb_id when starting from IMDb ids
- If content was previously valid, re-search by title to locate the new/alternate TMDB entry
- Catch this 404 upstream and fall back to a search-based flow rather than surfacing the error to the user
Example fix
# before
movie = service.get_detail(hallucinated_id) # MovieServiceError 404
# after
try:
movie = service.get_detail(movie_id)
except MovieServiceError as e:
if e.status_code != 404:
raise
candidates = service.search(title_hint, year=year_hint)
if not candidates:
raise
movie = service.get_detail(candidates[0].id) Defensive patterns
Strategy: fallback
Validate before calling
def plausible_movie_id(mid) -> bool:
return isinstance(mid, int) and 0 < mid < 100_000_000 Try / catch
try:
return service.get_detail(mid)
except MovieServiceError as e:
if e.status_code != 404:
raise
hits = service.search(title_hint, year=year_hint)
return service.get_detail(hits[0].id) if hits else None Prevention
- Never trust ids from LLM output verbatim — resolve via search/find first
- When starting from IMDb ids, use TMDB /find?external_source=imdb_id instead of guessing
- Cache known-good ids so 404s trigger a one-time re-resolution, not per-request failures
When it happens
Trigger: get_detail(movie_id) with an arbitrary/hallucinated id (LLM-generated ids are a classic source); id from a different TMDB region profile where the title is geo-blocked; very large ids beyond assigned range; a formerly valid id removed after a DMCA takedown; passing a TV show id to the /movie/ endpoint.
Common situations: Recommendation agent inventing plausible-looking ids; stale ids persisted from an old crawl; ids harvested from a third-party dataset that actually uses IMDb ids (tt...) rather than TMDB numeric ids.
Related errors
- TMDB 未配置:请在 .env 设置 TMDB_ACCESS_TOKEN 或 TMDB_API_KEY
- TMDB 请求超时: {e}
- TMDB 网络错误: {e}
- TMDB 鉴权失败:请检查 Access Token / API Key
- TMDB 请求失败: HTTP {resp.status_code}, {resp.text[:200]}
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/61c5844957d6e065.
Report an issue: GitHub.