infiniflow/ragflow · error · TypeError

Querit API response field statuses must be an array.

Error message

Querit API response field statuses must be an array.

What it means

TypeError from _validate_contents_response(): when the response object contains a 'statuses' key (per-URL crawl statuses), its value must be an array. Like 'results', the key is optional but type-checked when present.

Source

Thrown at agent/tools/querit.py:393

    for url in urls:
        parsed = urlparse(url)
        if parsed.scheme not in {"http", "https"} or not parsed.netloc:
            raise ValueError("Querit urls must be absolute HTTP or HTTPS URLs.")
    if format not in QUERIT_CONTENT_FORMATS:
        raise ValueError("Querit format must be text, markdown, or html.")
    if type(crawl_timeout) is not int or not 1 <= crawl_timeout <= 60:
        raise ValueError("Querit crawl_timeout must be an integer from 1 to 60.")
    if type(extras_meta) is not bool:
        raise ValueError("Querit extras_meta must be a boolean.")


def _validate_contents_response(response_data: Any) -> None:
    if not isinstance(response_data, dict):
        raise TypeError("Querit API response must be a JSON object.")
    if "results" in response_data and not isinstance(response_data["results"], list):
        raise TypeError("Querit API response field results must be an array.")
    if "statuses" in response_data and not isinstance(response_data["statuses"], list):
        raise TypeError("Querit API response field statuses must be an array.")


def _validate_search_inputs(
    count: Any,
    chunks_per_doc: Any,
    time_range: Any,
    site_include: Any,
    site_exclude: Any,
    country_include: Any,
    language_include: Any,
) -> None:
    if type(count) is not int or count < 1:
        raise ValueError("Querit count must be an integer greater than or equal to 1.")
    if chunks_per_doc is not None and (type(chunks_per_doc) is not int or not 1 <= chunks_per_doc <= 3):
        raise ValueError("Querit chunks_per_doc must be an integer from 1 to 3.")
    if type(time_range) is not str:
        raise ValueError("Querit time_range must be a string.")
    if time_range and not TIME_RANGE_PATTERN.fullmatch(time_range):

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Confirm via curl that statuses is an array aligned with the request urls order.
  2. Report/pin the API contract — object-shaped statuses are a breaking change for this client.
  3. Adapt in a wrapper if you control the server: emit [] not null/''.
  4. Update mocks.
Defensive patterns

Strategy: type-guard

Validate before calling

def contents_statuses_ok(data: dict) -> bool:
    return "statuses" not in data or isinstance(data["statuses"], list)

Type guard

from typing import Any
def has_list_statuses(v: Any) -> bool:
    return not isinstance(v, dict) or "statuses" not in v or isinstance(v["statuses"], list)

Try / catch

try:
    querit_contents._invoke(urls=urls)
except TypeError as e:
    if "statuses must be an array" in str(e):
        alert_api_contract_drift(e)
    raise

Prevention

When it happens

Trigger: A contents response with {"statuses": {"0": "ok"}} (object keyed by index) or {"statuses": "ok"} instead of the expected per-URL array.

Common situations: API schema drift converting the statuses array to a map; partial responses where statuses is a sentinel string; contract tests with loose typing.

Related errors


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