BerriAI/litellm · error · ValueError
num must be between {NUM_MIN} and {NUM_MAX}, got {self.num}
Error message
num must be between {NUM_MIN} and {NUM_MAX}, got {self.num} What it means
Constructor validation for the apiserpent (SerpentAPI) search defaults dataclass. 'num' (results per request) must be an int in [1, 100]; the __post_init__ hook rejects anything outside that absolute range with a ValueError. The deep-search floor of 10 is enforced separately in the transform layer, so values 1-9 pass here but may be clamped later for deep endpoints.
Source
Thrown at litellm/llms/apiserpent/search/defaults.py:47
the rest are always sent so behavior is deterministic regardless of any
server-side defaults.
"""
engine: SearchEngine = "google"
country: str = "us"
num: int = 10
format: ResponseFormat = "full"
pages: int | None = None
freshness: Freshness | None = None
safe: SafeSearch | None = None
language: str | None = None
pixel_position: bool | None = None
def __post_init__(self) -> None:
# num's deep-search floor (NUM_MIN_DEEP) is endpoint-specific and enforced
# in the transform layer; here we only bound the absolute range.
if not NUM_MIN <= self.num <= NUM_MAX:
raise ValueError(f"num must be between {NUM_MIN} and {NUM_MAX}, got {self.num}")
if self.pages is not None and not PAGES_MIN <= self.pages <= PAGES_MAX:
raise ValueError(f"pages must be between {PAGES_MIN} and {PAGES_MAX}, got {self.pages}")
def to_request_params(self) -> dict:
"""Return non-None fields as request params, booleans lowercased."""
params: Final[dict] = {}
for key, value in asdict(self).items():
if value is None:
continue
params[key] = str(value).lower() if isinstance(value, bool) else value
return params
@classmethod
def field_names(cls) -> set:
return set(cls.__dataclass_fields__.keys())
QUICK_SEARCH_PATH: Final = "/api/search/quick"View on GitHub (pinned to 6c2dcb801b)
Solutions
- Clamp num to 1..100 before constructing the object.
- For more results, use the 'pages' parameter (1..10) instead of a huge num.
- Remember deep-search endpoints enforce a floor of 10 — pass >= 10 for deep search.
Example fix
# before params = SearchDefaults(num=200) # after params = SearchDefaults(num=100, pages=2) # 2 pages of 100 instead of num=200
Defensive patterns
Strategy: validation
Validate before calling
NUM_MIN, NUM_MAX = 1, 100
def clamp_num(num: int) -> int:
return max(NUM_MIN, min(num, NUM_MAX)) Type guard
def is_valid_num(num: object) -> bool:
return isinstance(num, int) and not isinstance(num, bool) and 1 <= num <= 100 Try / catch
try:
params = SearchDefaults(num=num)
except ValueError:
params = SearchDefaults(num=min(100, max(1, num))) Prevention
- Clamp user-supplied result counts to 1..100 before constructing search params.
- Use pages (1..10) for more results instead of large num.
- For deep search, remember the separate floor of 10.
When it happens
Trigger: Instantiating the search defaults with num=0, a negative number, or num>100 — e.g. num=200 to 'get more results', or num=0 to mean 'unlimited'.
Common situations: Porting configs from APIs that allow num=0 or 1000; user-facing search UIs letting users request arbitrary result counts; pagination math that computes num as page_size * page and overflows the cap.
Related errors
- pages must be between {PAGES_MIN} and {PAGES_MAX}, got {self
- APISERPENT_API_KEY is not set. Set `APISERPENT_API_KEY` envi
- Invalid mode: {custom_auth_settings['mode']}
- Filtering by 'provider' is not supported when using managed
- Filtering by 'target_model_names' is not supported when usin
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/1821b65042a0296e.
Report an issue: GitHub.