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

  1. 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.
  2. 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.
  3. 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

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


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/9e47555402984df2. Report an issue: GitHub.