vxcontrol/pentagi · error · Retryable

failed to do request: %w

Error message

failed to do request: %w

What it means

The HTTP GET to the SearxNG instance failed at transport level (client.Do returned an error). This is wrapped as Retryable(err, 0), meaning the search orchestrator may retry it and/or fall back to other engines. Typical causes: DNS failure, connection refused, TLS handshake failure, or the request context being canceled/timed out (client.Timeout default 30s from SearxngTimeout).

Source

Thrown at backend/pkg/tools/searchers/searxng.go:125

	apiURL.RawQuery = params.Encode()

	client, err := system.GetHTTPClient(s.cfg)
	if err != nil {
		return "", Fatal(fmt.Errorf("failed to create http client: %w", err))
	}

	client.Timeout = s.timeout()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL.String(), nil)
	if err != nil {
		return "", Fatal(fmt.Errorf("failed to create request: %w", err))
	}

	req.Header.Set("User-Agent", "PentAGI/1.0")

	resp, err := client.Do(req)
	if err != nil {
		return "", Retryable(fmt.Errorf("failed to do request: %w", err), 0)
	}
	defer resp.Body.Close()

	return s.parseHTTPResponse(resp, query)
}

func (s *searxng) parseHTTPResponse(resp *http.Response, query string) (string, error) {
	if resp.StatusCode != http.StatusOK {
		err := fmt.Errorf("unexpected status code: %d", resp.StatusCode)
		if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {
			return "", Retryable(err, 0)
		}
		return "", Fatal(err)
	}

	var searxngResponse SearxngResponse
	if err := json.NewDecoder(resp.Body).Decode(&searxngResponse); err != nil {
		return "", Fatal(fmt.Errorf("failed to decode response body: %w", err))

View on GitHub (pinned to ea665308ba)

Solutions

  1. Verify the SearxNG instance is up and reachable: curl the SEARXNG_URL from inside the backend container
  2. Correct the hostname/port in SEARXNG_URL (must match the docker-compose service name and port)
  3. Check docker network connectivity and that both containers share the network
  4. If HTTPS, ensure the SearxNG certificate is trusted (custom CA config) or use plain HTTP internally
  5. Increase SEARXNG_TIMEOUT if the instance is slow; the error is Retryable so transient outages self-heal via the fallback chain

Example fix

// before (docker-compose.yml)
SEARXNG_URL=http://searx:8080
# after (docker-compose.yml)
SEARXNG_URL=http://searxng:8080
Defensive patterns

Strategy: retry

Validate before calling

// preflight reachability check before enabling the engine
resp, err := http.Head(baseURL)
if err != nil {
    log.Printf("searxng unreachable, will rely on fallback engines: %v", err)
}

Try / catch

result, err := searxngSearcher.Handle(ctx, req)
if err != nil && isRetryable(err) {
    select {
    case <-ctx.Done():
        return ctx.Err()
    case <-time.After(backoff):
        result, err = searxngSearcher.Handle(ctx, req)
    }
}
if err != nil {
    result, err = fallbackSearcher.Handle(ctx, req)
}

Prevention

When it happens

Trigger: SearxNG container not running or wrong host/port in SEARXNG_URL; network policy blocking container-to-container traffic; TLS certificate error against an HTTPS SearxNG instance; slow SearxNG exceeding the configured SEARXNG_TIMEOUT (default 30s); ctx canceled because the parent flow finished.

Common situations: docker-compose service name mismatch in SEARXNG_URL (e.g. http://searx:8080 vs http://searxng:8080); SearxNG crashed/OOMed; self-signed certificate not trusted by the Go client; reverse proxy in front of SearxNG down.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/7893113e65f4b292. Report an issue: GitHub.