Tencent/WeKnora · error

failed to execute Exa request: %w

Error message

failed to execute Exa request: %w

What it means

Wraps errors from p.client.Do(req) when the HTTP round-trip to the Exa API fails before a response is returned. Causes include DNS failures, unreachable host, TLS problems, client timeout, or context cancellation during the request.

Source

Thrown at internal/infrastructure/web_search/exa.go:97

		Contents: exaContents{
			Highlights: true,
			Text:       p.includeText,
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to marshal Exa request: %w", err)
	}
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.baseURL, bytes.NewReader(bodyBytes))
	if err != nil {
		return nil, fmt.Errorf("failed to create Exa request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-api-key", p.apiKey)

	logger.Infof(ctx, "[WebSearch][Exa] query=%q maxResults=%d url=%s", query, maxResults, p.baseURL)
	resp, err := p.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to execute Exa request: %w", err)
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(io.LimitReader(resp.Body, maxExaResponseBytes))
	if err != nil {
		return nil, fmt.Errorf("failed to read Exa response: %w", err)
	}
	if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
		logger.Warnf(ctx, "[WebSearch][Exa] API returned status %d: %s", resp.StatusCode, string(body))
		return nil, fmt.Errorf("exa API returned status %d: %s", resp.StatusCode, string(body))
	}

	var data exaSearchResponse
	if err := json.Unmarshal(body, &data); err != nil {
		return nil, fmt.Errorf("failed to unmarshal Exa response: %w", err)
	}
	if data.Error != "" {
		return nil, fmt.Errorf("exa API error: %s", data.Error)
	}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Confirm outbound connectivity to api.exa.ai:443 from the deployment
  2. Check/fix the proxyURL in provider parameters
  3. Increase defaultExaTimeout if large searches time out
  4. Add bounded retry with backoff for transient failures
  5. Inspect the unwrapped *url.Error for timeout vs connection specifics
Defensive patterns

Strategy: retry

Validate before calling

conn, err := net.DialTimeout("tcp", "api.exa.ai:443", 3*time.Second)
if err != nil {
    return fmt.Errorf("no egress to api.exa.ai: %w", err)
}
conn.Close()

Try / catch

results, err := provider.Search(ctx, query, 10, false)
if err != nil {
    var ne net.Error
    if errors.As(err, &ne) && ne.Timeout() || errors.Is(err, context.DeadlineExceeded) {
        return retryWithBackoff(ctx, query)
    }
    return fallbackProvider.Search(ctx, query, 10, false)
}

Prevention

When it happens

Trigger: Calling Search when the network cannot reach api.exa.ai, the configured proxy is down or wrong, the client timeout (defaultExaTimeout) expires, or ctx is canceled mid-request.

Common situations: No egress to api.exa.ai from a private cluster, invalid proxyURL parameter, firewall blocking the domain, slow Exa responses exceeding the client timeout, revoked DNS in rotating environments.

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 Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/910a7e3faf214f33. Report an issue: GitHub.