assafelovic/gpt-researcher · error · Exception

Error querying SearxNG: {str(e)}

Error message

Error querying SearxNG: {str(e)}

What it means

Exception raised by SearxNG search() when the HTTP request to the instance fails at the transport/HTTP layer — raise_for_status() throws, or a connection/timeout error occurs — wrapped into Exception(f"Error querying SearxNG: {e}"). The embedded text carries the underlying requests error (DNS failure, 403, timeout, etc.).

Source

Thrown at gpt_researcher/retrievers/searx/searx.py:86

        search_url = urljoin(self.base_url, "search")
        # TODO: Add support for query domains
        params = {
            # The search query.
            'q': self.query,
            # Output format of results. Format needs to be activated in searxng config.
            'format': 'json'
        }

        try:
            response = requests.get(
                search_url,
                params=params,
                headers={'Accept': 'application/json'}
            )
            response.raise_for_status()
            results = response.json()
        except requests.exceptions.RequestException as e:
            raise Exception(f"Error querying SearxNG: {str(e)}")
        except json.JSONDecodeError:
            raise Exception("Error parsing SearxNG response")

        if not isinstance(results, dict):
            return []

        search_response = []
        raw_results = results.get('results', [])
        if not isinstance(raw_results, list):
            return []

        for result in raw_results:
            if not isinstance(result, dict):
                continue
            href = result.get('url') or result.get('href') or ''
            if not href:
                continue
            body = result.get('content') or result.get('snippet') or ''

View on GitHub (pinned to 6f998577d5)

Solutions

  1. Read the embedded requests error: 403 usually means JSON output disabled — enable it in the instance's settings.yml.
  2. Test the instance manually: curl 'SEARX_URL/search?q=test&format=json'.
  3. Point SEARX_URL at a healthy instance (or self-host one with JSON enabled) and retry.
  4. Add retry/timeout handling for flaky public instances.

Example fix

# before
results = retriever.search(max_results=10)

# after
try:
    results = retriever.search(max_results=10)
except Exception as e:
    logger.warning(f"SearxNG unavailable: {e}")
    results = []
Defensive patterns

Strategy: fallback

Validate before calling

import requests, os
url = os.environ["SEARX_URL"].rstrip('/') + '/'
def searx_healthy():
    try:
        r = requests.get(url + 'search', params={'q': 'test', 'format': 'json'}, timeout=5)
        return r.status_code == 200
    except requests.RequestException:
        return False

Type guard

null

Try / catch

try:
    results = retriever.search(max_results=10)
except Exception as e:
    if "Error querying SearxNG" in str(e):
        results = backup_retriever.search(max_results=10)
    else:
        raise

Prevention

When it happens

Trigger: search() issues requests.get(url, params, headers); any requests.exceptions.RequestException (ConnectionError, Timeout, HTTPError from a 4xx/5xx status) triggers it.

Common situations: SearX_URL pointing to a dead/blocked instance, instance returning 403 (bot detection or JSON format disabled), timeouts on slow public instances, or network/DNS issues from the host.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of assafelovic/gpt-researcher@6f998577d5 (2026-08-28). Data as JSON: /api/errors/d201e23930fad6b4. Report an issue: GitHub.