datawhalechina/hello-agents · warning · MovieServiceError
movie_id 必须为正整数
Error message
movie_id 必须为正整数
What it means
MovieServiceError with status_code=400 raised by get_detail when movie_id <= 0. This is an input-validation guard that fires before any network call: TMDB numeric ids are positive integers, so zero or negative values are caller bugs (often from unparsed user input or an LLM emitting a sentinel like 0 or -1).
Source
Thrown at Co-creation-projects/aatanxiao12-beep-YingQian/backend/app/services/movie_service.py:296
genres=genre_names,
runtime=runtime,
rating=item.get("vote_average"),
poster_url=self._poster_url(item.get("poster_path")),
overview=item.get("overview") or "",
tagline=(item.get("tagline") or "").strip() or None,
original_title=original_title,
vote_count=vote_count,
original_language=(item.get("original_language") or "").strip() or None,
countries=countries,
directors=directors,
cast=cast_names,
tmdb_url=f"https://www.themoviedb.org/movie/{movie_id}",
)
def get_detail(self, movie_id: int) -> MovieDetail:
"""按 id 取电影详情(含 credits:导演 / 主演)。"""
if movie_id <= 0:
raise MovieServiceError("movie_id 必须为正整数", status_code=400)
data = self._get(
f"/movie/{movie_id}",
{"append_to_response": "credits"},
)
return self._map_detail(data)
def search(
self,
q: str,
year: Optional[int] = None,
page: int = 1,
) -> List[CandidateMovie]:
"""按关键词搜索电影(TMDB GET /search/movie)。"""
query = (q or "").strip()
if not query:
raise MovieServiceError("搜索关键词 q 不能为空", status_code=400)
View on GitHub (pinned to 606a07d341)
Solutions
- Validate at the API boundary (FastAPI path/query param with gt=0) so bad input never reaches the service
- Trace where the non-positive id originated and fix the default/parsing there
- In agent pipelines, re-search for the title when an LLM emits an invalid id instead of forwarding it
Example fix
# before
@app.get("/movies/{movie_id}")
async def get_movie(movie_id: int):
return service.get_detail(movie_id) # service raises 400
# after
from fastapi import Path
@app.get("/movies/{movie_id}")
async def get_movie(
movie_id: int = Path(..., gt=0),
):
return service.get_detail(movie_id) # FastAPI rejects <=0 with 422 Defensive patterns
Strategy: validation
Validate before calling
def valid_movie_id(mid) -> bool:
return isinstance(mid, int) and not isinstance(mid, bool) and mid > 0 Type guard
from typing import Any
def is_positive_int(v: Any) -> bool:
return isinstance(v, int) and not isinstance(v, bool) and v > 0 Prevention
- Declare FastAPI params with gt=0 (or pydantic Field(gt=0)) so the framework rejects bad ids with 422
- Never default ids to 0 — use None and require the caller to supply a real id
- Validate LLM tool outputs (movie ids) against is_positive_int before use
When it happens
Trigger: get_detail(0), get_detail(-1); movie_id parsed from free text where int() fell back to a default 0; None coerced to 0; id arithmetic underflow; frontend sending an empty form field that serializes to 0.
Common situations: LLM tool-calling emitting an invalid id; form default value of 0 slipping through; unit tests passing 0 as a dummy; ids read from a CSV with empty cells converted via int(cell or 0).
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/4d3b8bbe4ebf5044.
Report an issue: GitHub.