infiniflow/ragflow · error · ValueError

Invalid results format from SearXNG

Error message

Invalid results format from SearXNG

What it means

After the SearXNG response body passes the dict check, the component reads data.get('results', []) and requires it to be a list (agent/tools/searxng.py:116). A 'results' key holding an object, string, number, or null raises ValueError('Invalid results format from SearXNG'). The body was JSON but does not follow the SearXNG search-response shape.

Source

Thrown at agent/tools/searxng.py:116

            try:
                search_params = {"q": query, "format": "json", "categories": "general", "language": "auto", "safesearch": 1, "pageno": 1}

                with pin_dns(_ssrf_hostname, _ssrf_ip):
                    response = requests.get(f"{searxng_url}/search", params=search_params, timeout=10)
                response.raise_for_status()

                if self.check_if_canceled("SearXNG processing"):
                    return

                data = response.json()

                if not data or not isinstance(data, dict):
                    raise ValueError("Invalid response from SearXNG")

                results = data.get("results", [])
                if not isinstance(results, list):
                    raise ValueError("Invalid results format from SearXNG")

                results = results[: self._param.top_n]

                if self.check_if_canceled("SearXNG processing"):
                    return

                self._retrieve_chunks(results, get_title=lambda r: r.get("title", ""), get_url=lambda r: r.get("url", ""), get_content=lambda r: r.get("content", ""))

                self.set_output("json", results)
                return self.output("formalized_content")

            except requests.RequestException as e:
                if self.check_if_canceled("SearXNG processing"):
                    return

                last_e = f"Network error: {e}"
                logging.exception(f"SearXNG network error: {e}")
                time.sleep(self._param.delay_after_error)

View on GitHub (pinned to 554fb1133a)

Solutions

  1. curl the exact URL the component uses ('{searxng_url}/search?q=test&format=json') and confirm the top-level 'results' key is a JSON array.
  2. Point searxng_url at the SearXNG base URL (e.g. http://searxng:8080), not at a proxy or admin endpoint that reshapes bodies.
  3. Disable/adjust SearXNG plugins or proxy transforms that alter the response structure.
  4. If the body is an error envelope, fix the underlying error (bad format, limiter block) first - it is not a client-side parsing bug.

Example fix

# verify expected shape
curl 'http://searxng:8080/search?q=test&format=json'
# expected: {"query": "test", "results": [{"title": ..., "url": ..., "content": ...}, ...]}
Defensive patterns

Strategy: try-catch

Validate before calling

data = response.json()
results = data.get("results") if isinstance(data, dict) else None
if not isinstance(results, list):
    raise ValueError(f"unexpected SearXNG shape: {type(results).__name__}")

Type guard

def is_searxng_payload(data) -> bool:
    return isinstance(data, dict) and isinstance(data.get("results", []), list)

Try / catch

try:
    ...
except ValueError as e:
    if "results format" in str(e):
        log.raw_body(data)  # capture the malformed payload for diagnosis
        return []          # degrade to no results rather than failing the canvas

Prevention

When it happens

Trigger: The endpoint returns a JSON error object like {"error": ...} or {"results": {"error": ...}}; a proxy returns a JSON API error envelope; a non-SearXNG JSON service is configured at searxng_url; a SearXNG plugin mutates the response shape.

Common situations: SearXNG behind an API gateway that wraps responses; wrong base URL pointing at a JSON admin/route instead of the search route; version differences or plugins altering the payload.

Related errors


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