{"record":{"id":"f2d734011fc085fd","repo":"vxcontrol/pentagi","slug":"unexpected-status-code-d-f2d734","errorCode":null,"errorMessage":"unexpected status code: %d","messagePattern":"unexpected status code: (.+?)","errorType":"http","errorClass":"Fatal","httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/searchers/tavily.go","lineNumber":170,"sourceCode":"\t\treturn \"\", Fatal(fmt.Errorf(\"API key is wrong\"))\n\tcase http.StatusForbidden:\n\t\treturn \"\", Fatal(fmt.Errorf(\"the endpoint requested is hidden for administrators only\"))\n\tcase http.StatusNotFound:\n\t\treturn \"\", Fatal(fmt.Errorf(\"the specified endpoint could not be found\"))\n\tcase http.StatusMethodNotAllowed:\n\t\treturn \"\", Fatal(fmt.Errorf(\"there need to try to access an endpoint with an invalid method\"))\n\tcase http.StatusTooManyRequests:\n\t\treturn \"\", Retryable(fmt.Errorf(\"there are requesting too many results\"), 0)\n\tcase http.StatusInternalServerError:\n\t\treturn \"\", Retryable(fmt.Errorf(\"there had a problem with our server. try again later\"), 0)\n\tcase http.StatusBadGateway:\n\t\treturn \"\", Retryable(fmt.Errorf(\"there was a problem with the server. Please try again later\"), 0)\n\tcase http.StatusServiceUnavailable:\n\t\treturn \"\", Retryable(fmt.Errorf(\"there are temporarily offline for maintenance. please try again later\"), 0)\n\tcase http.StatusGatewayTimeout:\n\t\treturn \"\", Retryable(fmt.Errorf(\"there are temporarily offline for maintenance. please try again later\"), 0)\n\tdefault:\n\t\treturn \"\", Fatal(fmt.Errorf(\"unexpected status code: %d\", resp.StatusCode))\n\t}\n}\n\nfunc (t *tavily) buildTavilyResult(ctx context.Context, result *tavilySearchResult) string {\n\tvar writer strings.Builder\n\twriter.WriteString(\"# Answer\\n\\n\")\n\twriter.WriteString(result.Answer)\n\twriter.WriteString(\"\\n\\n# Links\\n\\n\")\n\n\tisRawContentExists := false\n\tfor i, result := range result.Results {\n\t\twriter.WriteString(fmt.Sprintf(\"## %d. %s\\n\\n\", i+1, result.Title))\n\t\twriter.WriteString(fmt.Sprintf(\"* URL %s\\n\", result.URL))\n\t\twriter.WriteString(fmt.Sprintf(\"* Match score %3.3f\\n\\n\", result.Score))\n\t\twriter.WriteString(fmt.Sprintf(\"### Short content\\n\\n%s\\n\\n\", result.Content))\n\t\tif result.RawContent != nil {\n\t\t\tisRawContentExists = true\n\t\t}","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/searchers/tavily.go#L152-L188","documentation":"parseHTTPResponse's default branch wraps any Tavily response status not explicitly handled (not 429/500/502/503/504) into a Fatal error: 'unexpected status code: %d'. Fatal means retrying the same engine is pointless — the caller should fall back to another searcher or surface the error.","triggerScenarios":"Any non-200 status outside the handled set — e.g. 400 Bad Request from a malformed query, 401/403 from an invalid or expired TAVILY_API_KEY, 404 from a changed API endpoint, or 418/429 edge cases not matched.","commonSituations":"Expired or wrong Tavily API key (401/403); Tavily API contract change (new status codes); request blocked by WAF (403); malformed plan/billing state (402).","solutions":["Log the actual status code — the message includes it via %d — and fix the root cause (usually auth).","Verify TAVILY_API_KEY is set and valid; test with curl against api.tavily.com.","Update the searcher if Tavily introduced new status codes worth handling explicitly.","Ensure the orchestrator treats Fatal errors by switching engines, not retrying."],"exampleFix":"// before: ignoring the status code detail\nif err != nil { return \"\", err }\n// after: inspect wrapped error and remediate auth issues\nvar fatal *searchers.FatalError\nif errors.As(err, &fatal) && strings.Contains(fatal.Error(), \"401\") {\n    return \"\", fmt.Errorf(\"tavily auth failed: check TAVILY_API_KEY\")\n}","handlingStrategy":"fallback","validationCode":"if os.Getenv(\"TAVILY_API_KEY\") == \"\" {\n    return errors.New(\"TAVILY_API_KEY not configured; tavily engine unavailable\")\n}","typeGuard":"func isFatalSearcherError(err error) bool {\n    var f *searchers.FatalError\n    return errors.As(err, &f)\n}","tryCatchPattern":"result, err := tavilySearcher.Handle(ctx, req)\nvar f *searchers.FatalError\nif errors.As(err, &f) {\n    log.Errorf(\"tavily fatal: %v\", f)\n    return fallbackEngine.Handle(ctx, req)\n}","preventionTips":["Validate TAVILY_API_KEY at startup with a lightweight authenticated ping","Never retry Fatal errors — switch engines immediately","Log full status codes to detect Tavily API contract changes early"],"tags":["http","search","tavily","status-code","fatal"],"backgroundTag":"unexpected-http-status-code","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}