{"record":{"id":"2b9b61a3e3a3d256","repo":"Tencent/WeKnora","slug":"tavily-api-returned-status-d-s","errorCode":null,"errorMessage":"tavily API returned status %d: %s","messagePattern":"tavily API returned status (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/web_search/tavily.go","lineNumber":93,"sourceCode":"\t\treturn nil, fmt.Errorf(\"failed to marshal request: %w\", err)\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, \"POST\", p.baseURL, bytes.NewReader(bodyBytes))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresp, err := p.client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to execute request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\trespBody, _ := io.ReadAll(resp.Body)\n\t\tlogger.Warnf(ctx, \"[WebSearch][Tavily] API returned status %d: %s\", resp.StatusCode, string(respBody))\n\t\treturn nil, fmt.Errorf(\"tavily API returned status %d: %s\", resp.StatusCode, string(respBody))\n\t}\n\n\trespBody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read response: %w\", err)\n\t}\n\n\tvar respData tavilySearchResponse\n\tif err := json.Unmarshal(respBody, &respData); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal response: %w\", err)\n\t}\n\n\tresults := make([]*types.WebSearchResult, 0, len(respData.Results))\n\tfor _, item := range respData.Results {\n\t\tresult := &types.WebSearchResult{\n\t\t\tTitle:   item.Title,\n\t\t\tURL:     item.URL,\n\t\t\tSnippet: item.Content,","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/tavily.go#L75-L111","documentation":"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.","triggerScenarios":"Calling provider.Search and receiving HTTP 401 (invalid API key), 400 (malformed request body), 429 (rate limit), or 5xx from the Tavily API.","commonSituations":"Expired or wrong TAVILY_API_KEY, exceeding plan quota/rate limits, Tavily API outages or breaking API changes, or account suspension.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// validate config before constructing the provider\nif os.Getenv(\"TAVILY_API_KEY\") == \"\" { return errors.New(\"TAVILY_API_KEY not set\") }","typeGuard":"func isHTTPStatusErr(err error) (code int, body string, ok bool) {\n    m := regexp.MustCompile(`tavily API returned status (\\d+): (.*)`).FindStringSubmatch(err.Error())\n    if m == nil { return 0, \"\", false }\n    code, _ = strconv.Atoi(m[1])\n    return code, m[2], true\n}","tryCatchPattern":"results, err := provider.Search(ctx, q, 5, false)\nif err != nil {\n    if code, body, ok := isHTTPStatusErr(err); ok {\n        switch {\n        case code == 401: return fmt.Errorf(\"invalid tavily API key: %s\", body)\n        case code == 429: return retryAfterBackoff(ctx)\n        case code >= 500: return retryWithBackoff(ctx)\n        }\n    }\n    return err\n}","preventionTips":["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"],"tags":["http","api-error","web-search","tavily"],"backgroundTag":"http-non-200-response","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}