vxcontrol/pentagi · warning · Retryable

request to Sploitus failed: %w

Error message

request to Sploitus failed: %w

What it means

client.Do(req) failed at the transport level (DNS failure, connection refused/reset, TLS error, timeout, or context cancellation); the searcher classifies this as Retryable with delay 0 so the web_search orchestrator may retry against fallback engines. Sploitus sits behind Cloudflare, so blocked/intercepted connections can also surface here.

Source

Thrown at backend/pkg/tools/searchers/sploitus.go:155

	// Mimic Chrome browser headers to bypass Cloudflare protection
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Accept-Language", "en-US,en;q=0.9")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Origin", "https://sploitus.com")
	req.Header.Set("Referer", referer)
	req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36")
	req.Header.Set("sec-ch-ua", `"Not:A-Brand";v="99", "Google Chrome";v="145", "Chromium";v="145"`)
	req.Header.Set("sec-ch-ua-mobile", "?0")
	req.Header.Set("sec-ch-ua-platform", `"macOS"`)
	req.Header.Set("sec-fetch-dest", "empty")
	req.Header.Set("sec-fetch-mode", "cors")
	req.Header.Set("sec-fetch-site", "same-origin")
	req.Header.Set("DNT", "1")

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

	// Sploitus API returns 499 (and sometimes 422) when its rate limit is temporarily
	// exceeded — a transient condition that may clear on retry.
	if resp.StatusCode == 499 || resp.StatusCode == 422 {
		return "", Retryable(fmt.Errorf("Sploitus API rate limit exceeded (HTTP %d), please try again later", resp.StatusCode), 0)
	}

	if resp.StatusCode != http.StatusOK {
		err := fmt.Errorf("Sploitus API returned HTTP %d", resp.StatusCode)
		if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {
			return "", Retryable(err, 0)
		}
		return "", Fatal(err)
	}

	var apiResp sploitusResponse

View on GitHub (pinned to ea665308ba)

Solutions

  1. Read the wrapped error: 'no such host' => fix DNS, 'connection refused' => check outbound firewall/proxy
  2. Confirm the container can reach https://sploitus.com (curl from inside the container)
  3. Check whether sploitusRequestTimeout is too short and raise it if requests are timing out
  4. Verify the flow context was not cancelled upstream; if intentional, ignore this error

Example fix

// before
client.Timeout = 2 * time.Second // too tight on slow links
// after
client.Timeout = 15 * time.Second
Defensive patterns

Strategy: retry

Validate before calling

if err := ctx.Err(); err != nil {
    return fmt.Errorf("context already cancelled: %w", err)
}

Try / catch

resp, err := client.Do(req)
if err != nil {
    // Retryable: attempt backoff or fall back to another searcher engine
    return "", Retryable(fmt.Errorf("request to Sploitus failed: %w", err), 0)
}

Prevention

When it happens

Trigger: Handle() calls client.Do(req) on the POST to sploitus.com; any error from the http.Client transport — network unreachable, DNS NXDOMAIN, sploitusRequestTimeout exceeded, ctx cancelled, TLS handshake failure.

Common situations: The PentAGI container has no outbound internet or DNS, a corporate proxy blocks sploitus.com, the timeout (sploitusRequestTimeout) is too small for slow networks, or the request context is cancelled when the flow is aborted.

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 vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/268fa2ae47a82b33. Report an issue: GitHub.