vxcontrol/pentagi · error

failed to create http client: %w

Error message

failed to create http client: %w

What it means

search() calls system.GetHTTPClient(d.cfg) to build a configured *http.Client (proxy/TLS settings from config). If client construction fails (typically invalid proxy URL or bad TLS material in the config), the error is wrapped and search aborts before any request is made. This then surfaces to Handle as a Fatal duckduckgo search failure.

Source

Thrown at backend/pkg/tools/searchers/duckduckgo.go:140

		obs.LogErrorOrCancel(logger, err, "failed to search in DuckDuckGo")
		// DuckDuckGo already retries transient failures internally (see search);
		// by the time an error surfaces here, moving to the next engine is the
		// right call rather than burning another round-trip on the same one.
		return "", Fatal(fmt.Errorf("duckduckgo search failed: %w", err))
	}

	return result, nil
}

// search performs a web search using DuckDuckGo
func (d *duckduckgo) search(ctx context.Context, query string, maxResults int) (string, error) {
	// Build form data for POST request
	formData := d.buildFormData(query)

	// Create HTTP client with proper configuration
	client, err := system.GetHTTPClient(d.cfg)
	if err != nil {
		return "", fmt.Errorf("failed to create http client: %w", err)
	}

	client.Timeout = duckduckgoTimeout

	// Execute request with retry logic
	var response *searchResponse
	for attempt := 0; attempt < duckduckgoMaxRetries; attempt++ {
		req, err := http.NewRequestWithContext(ctx, "POST", duckduckgoSearchURL, strings.NewReader(formData))
		if err != nil {
			return "", fmt.Errorf("failed to create search request: %w", err)
		}

		// Add necessary headers for POST request
		req.Header.Set("User-Agent", duckduckgoUserAgent)
		req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
		req.Header.Set("Accept-Language", "en-US,en;q=0.9")

View on GitHub (pinned to ea665308ba)

Solutions

  1. Check the wrapped error text for 'proxy' or 'tls'/'certificate' and fix the corresponding config value (valid URL like http://host:port).
  2. Verify proxy env vars reachable from inside the Docker container, not just the host.
  3. Unset the proxy config if no proxy is required so a direct client is built.
  4. Validate config at startup (config_test / env validation) to fail fast on malformed proxy URLs.

Example fix

// before (docker-compose.yml)
SEARCH_PROXY: 192.168.1.10:8080
// after
SEARCH_PROXY: http://192.168.1.10:8080
Defensive patterns

Strategy: validation

Validate before calling

// validate proxy URL from config before constructing the client
if proxy := cfg.SearchProxyURL; proxy != "" {
    if _, err := url.Parse(proxy); err != nil {
        return fmt.Errorf("invalid proxy URL %q: %w", proxy, err)
    }
}

Try / catch

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

Prevention

When it happens

Trigger: system.GetHTTPClient returns an error because the configured proxy address in *config.Config is malformed (unparseable URL) or TLS configuration (cert files) cannot be loaded.

Common situations: Misconfigured HTTP_PROXY/HTTPS_PROXY env or config proxy field (e.g. missing scheme, spaces); pointing at a proxy cert that doesn't exist on disk; typo in proxy URL in .env / docker-compose environment.

Related errors


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