infiniflow/ragflow · error · ValueError
{field_name} must contain at most {REST_API_MAX_IDS} IDs
Error message
{field_name} must contain at most {REST_API_MAX_IDS} IDs What it means
Thrown by validate_rest_api_ids in api/utils/pagination_utils.py when a request supplies a list of IDs (e.g. dataset_id, document_id lists) longer than the public REST API cap REST_API_MAX_IDS. The cap protects batch endpoints from oversized payloads. It is a plain ValueError raised before any database or tenant lookup happens.
Source
Thrown at api/utils/pagination_utils.py:50
def validate_rest_api_page_size(page_size) -> int:
"""Validate page_size, if invalid, silent fallback to default page_size, and validate it against the public maximum."""
try:
int_page_size = int(page_size)
except (TypeError, ValueError):
return DEFAULT_PAGE_SIZE
if int_page_size < 1:
return DEFAULT_PAGE_SIZE
if int_page_size > REST_API_MAX_PAGE_SIZE:
raise ValueError(f"page_size must be less than or equal to {REST_API_MAX_PAGE_SIZE}")
return int_page_size
def validate_rest_api_ids(ids: list | None, field_name: str = "ids") -> list | None:
"""Validate REST API ID lists against the public maximum."""
if ids is not None and len(ids) > REST_API_MAX_IDS:
raise ValueError(f"{field_name} must contain at most {REST_API_MAX_IDS} IDs")
return ids
View on GitHub (pinned to 554fb1133a)
Solutions
- Chunk the ID list client-side into batches of at most REST_API_MAX_IDS (check its value in api/utils/pagination_utils.py or the config constants) and issue one request per batch.
- If you genuinely need larger batches, ask the maintainer to raise REST_API_MAX_IDS or use an async task/job endpoint instead of the synchronous batch API.
- Add a unit assertion in your client code that fails fast when an outbound ID list exceeds the cap.
Example fix
# before
resp = client.delete("/api/v1/datasets", json={"ids": all_ids}) # 5000 ids
# after
MAX_IDS = 100 # must match REST_API_MAX_IDS
for i in range(0, len(all_ids), MAX_IDS):
resp = client.delete("/api/v1/datasets", json={"ids": all_ids[i:i+MAX_IDS]})
resp.raise_for_status() Defensive patterns
Strategy: validation
Validate before calling
MAX_IDS = 100 # keep in sync with REST_API_MAX_IDS
def safe_batches(ids: list[str], size: int = MAX_IDS) -> list[list[str]]:
if len(ids) > size:
return [ids[i:i+size] for i in range(0, len(ids), size)]
return [ids] Type guard
def is_within_id_cap(ids: list[str] | None) -> bool:
return ids is None or len(ids) <= REST_API_MAX_IDS Try / catch
try:
resp = api.delete_datasets(ids)
except ValueError as e:
if "at most" in str(e) and "IDs" in str(e):
for batch in chunks(ids, MAX_IDS):
api.delete_datasets(batch)
else:
raise Prevention
- Hard-code the REST_API_MAX_IDS value as a client constant and assert on every batch call.
- Never feed an unbounded SELECT result into a single batch request.
- Prefer job/async endpoints for bulk operations beyond the cap.
When it happens
Trigger: Calling a bulk REST endpoint (delete/update datasets or documents by IDs) with a 'ids' (or similarly named) array whose length exceeds REST_API_MAX_IDS, e.g. POST/PUT with hundreds of UUIDs in one request while the constant is 100 (or whatever the configured max is).
Common situations: Scripts that migrate or sync thousands of documents and pass the whole ID list in one call; frontend 'select all' actions that collect every row's ID; pagination bugs where an unbounded query result is fed directly into a batch delete.
Related errors
- page_size must be less than or equal to {REST_API_MAX_PAGE_S
- invalid_uuid_format
- main() must be defined or exported.
- main() must return a value. Use null for an empty result.
- main() returned a non-JSON-serializable value.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/9e47555402984df2.
Report an issue: GitHub.