Tencent/WeKnora · error
tavily API returned status %d: %s
Error message
tavily API returned status %d: %s
What it means
The Tavily API responded with a non-200 HTTP status. The provider logs the status and body via Warnf, then returns this error containing both. This is a server-side rejection (auth, rate limit, bad endpoint) rather than a client-side network failure.
Source
Thrown at internal/infrastructure/web_search/tavily.go:93
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
req, err := http.NewRequestWithContext(ctx, "POST", p.baseURL, bytes.NewReader(bodyBytes))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := p.client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to execute request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
respBody, _ := io.ReadAll(resp.Body)
logger.Warnf(ctx, "[WebSearch][Tavily] API returned status %d: %s", resp.StatusCode, string(respBody))
return nil, fmt.Errorf("tavily API returned status %d: %s", resp.StatusCode, string(respBody))
}
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response: %w", err)
}
var respData tavilySearchResponse
if err := json.Unmarshal(respBody, &respData); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
results := make([]*types.WebSearchResult, 0, len(respData.Results))
for _, item := range respData.Results {
result := &types.WebSearchResult{
Title: item.Title,
URL: item.URL,
Snippet: item.Content,View on GitHub (pinned to 988cbb0330)
Solutions
- Read the status code and body from the error message to identify the cause (401 vs 429 vs 5xx).
- Verify the Tavily API key is valid and active; regenerate it in the Tavily dashboard if needed.
- For 429, implement rate limiting or retry with exponential backoff respecting Retry-After.
- For 5xx, retry later and check the Tavily status page for outages.
Defensive patterns
Strategy: try-catch
Validate before calling
// validate config before constructing the provider
if os.Getenv("TAVILY_API_KEY") == "" { return errors.New("TAVILY_API_KEY not set") } Type guard
func isHTTPStatusErr(err error) (code int, body string, ok bool) {
m := regexp.MustCompile(`tavily API returned status (\d+): (.*)`).FindStringSubmatch(err.Error())
if m == nil { return 0, "", false }
code, _ = strconv.Atoi(m[1])
return code, m[2], true
} Try / catch
results, err := provider.Search(ctx, q, 5, false)
if err != nil {
if code, body, ok := isHTTPStatusErr(err); ok {
switch {
case code == 401: return fmt.Errorf("invalid tavily API key: %s", body)
case code == 429: return retryAfterBackoff(ctx)
case code >= 500: return retryWithBackoff(ctx)
}
}
return err
} Prevention
- Validate the API key at startup before serving traffic
- Monitor status codes and alert on 429/5xx rates
- Respect rate limits with client-side throttling
- Subscribe to Tavily status/changelog for outages and API changes
When it happens
Trigger: Calling provider.Search and receiving HTTP 401 (invalid API key), 400 (malformed request body), 429 (rate limit), or 5xx from the Tavily API.
Common situations: Expired or wrong TAVILY_API_KEY, exceeding plan quota/rate limits, Tavily API outages or breaking API changes, or account suspension.
Related errors
- poll error code=%d msg=%s
- bing API returned status %d: %s
- failed to create request: %w
- failed to create request: %w
- duckduckgo HTML returned status %d
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/2b9b61a3e3a3d256.
Report an issue: GitHub.