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

  1. Validate at the API boundary (FastAPI path/query param with gt=0) so bad input never reaches the service
  2. Trace where the non-positive id originated and fix the default/parsing there
  3. 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

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.