infiniflow/ragflow · error · ValueError
Invalid response from SearXNG
Error message
Invalid response from SearXNG
What it means
The SearXNG agent component GETs {searxng_url}/search with format=json and requires the parsed body to be a non-empty dict (agent/tools/searxng.py:112). A JSON body that is empty, a list, a string, or null raises ValueError('Invalid response from SearXNG'). This usually means the endpoint did not return a SearXNG JSON search payload at all.
Source
Thrown at agent/tools/searxng.py:112
last_e = ""
for _ in range(self._param.max_retries + 1):
if self.check_if_canceled("SearXNG processing"):
return
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"):
returnView on GitHub (pinned to 554fb1133a)
Solutions
- In SearXNG settings.yml enable the JSON format: search: formats: [html, json], then restart SearXNG.
- Verify manually: curl 'http://<host>/search?q=test&format=json' must return a JSON object with a results array.
- Check searxng_url has no trailing /search or wrong port - the code appends /search itself.
- If a proxy or bot-limiter intercepts the request, whitelist the RAGFlow server IP or adjust limiter settings.
Example fix
# before (searxng settings.yml)
search:
formats:
- html
# after
search:
formats:
- html
- json Defensive patterns
Strategy: try-catch
Validate before calling
import requests
def searxng_ready(base_url):
try:
r = requests.get(f"{base_url}/search", params={"q": "test", "format": "json"}, timeout=5)
return r.ok and isinstance(r.json(), dict)
except Exception:
return False Try / catch
try:
output = searxng_component.run(query)
except ValueError as e:
if "Invalid response" in str(e):
# endpoint healthy check failed: fall back to another search tool or surface config error
raise ConfigError("SearXNG JSON format disabled or URL wrong - check settings.yml") from e
raise Prevention
- Enable json in SearXNG search.formats at setup time and verify with curl.
- Monitor /search responses in staging after SearXNG upgrades - formats reset to defaults on some upgrades.
- Keep searxng_url as the bare base URL; the component appends /search.
When it happens
Trigger: searxng_url points at a SearXNG instance where the 'json' output format is disabled (default in modern SearXNG), so /search returns an HTML page or 403-related body; the URL points at a non-SearXNG service; a proxy returns a JSON array or error object; response.json() parses something that is not an object.
Common situations: Self-hosted SearXNG without enabling json in settings.yml search.formats; trailing-path mistakes in searxng_url; reverse proxy rewriting responses; SearXNG limiter returning a non-JSON block page.
Related errors
- Invalid results format from SearXNG
- Dataset({nm_or_id}) does not exist.
- No dataset is selected.
- No memory is selected.
- Failed to exchange authorization code for token: {e}
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/a84b141daac1c8b4.
Report an issue: GitHub.