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
- 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.
- Point searxng_url at the SearXNG base URL (e.g. http://searxng:8080), not at a proxy or admin endpoint that reshapes bodies.
- Disable/adjust SearXNG plugins or proxy transforms that alter the response structure.
- 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
- Pin the SearXNG version in deployments so response shape changes surface in testing.
- Do not put transforming proxies between RAGFlow and SearXNG.
- Smoke-test the exact /search?format=json call after every SearXNG config change.
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
- Invalid response from SearXNG
- Failed to delete search
- Failed to update search
- flow.formatTypeError
- HTTP {response.status_code}: {response.text}
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/4ddf7ca4be9abb2a.
Report an issue: GitHub.