{"record":{"id":"3bf80afefe554913","repo":"vxcontrol/pentagi","slug":"sploitus-api-returned-http-d","errorCode":null,"errorMessage":"Sploitus API returned HTTP %d","messagePattern":"Sploitus API returned HTTP (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/searchers/sploitus.go","lineNumber":166,"sourceCode":"\treq.Header.Set(\"sec-fetch-dest\", \"empty\")\n\treq.Header.Set(\"sec-fetch-mode\", \"cors\")\n\treq.Header.Set(\"sec-fetch-site\", \"same-origin\")\n\treq.Header.Set(\"DNT\", \"1\")\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn \"\", Retryable(fmt.Errorf(\"request to Sploitus failed: %w\", err), 0)\n\t}\n\tdefer resp.Body.Close()\n\n\t// Sploitus API returns 499 (and sometimes 422) when its rate limit is temporarily\n\t// exceeded — a transient condition that may clear on retry.\n\tif resp.StatusCode == 499 || resp.StatusCode == 422 {\n\t\treturn \"\", Retryable(fmt.Errorf(\"Sploitus API rate limit exceeded (HTTP %d), please try again later\", resp.StatusCode), 0)\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\terr := fmt.Errorf(\"Sploitus API returned HTTP %d\", resp.StatusCode)\n\t\tif resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {\n\t\t\treturn \"\", Retryable(err, 0)\n\t\t}\n\t\treturn \"\", Fatal(err)\n\t}\n\n\tvar apiResp sploitusResponse\n\tif err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {\n\t\treturn \"\", Fatal(fmt.Errorf(\"failed to decode Sploitus response: %w\", err))\n\t}\n\n\treturn formatSploitusResults(query, exploitType, limit, apiResp), nil\n}\n\n// IsAvailable returns true if the Sploitus tool is enabled and configured\nfunc (s *sploitus) IsAvailable() bool {\n\treturn s.enabled()\n}","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/searchers/sploitus.go#L148-L184","documentation":"Any Sploitus response status other than 200, 499, 422, and not 429/>=500 produces this Fatal error (no retry). 429 and 5xx are Retryable; everything else (403 Cloudflare block, 404, 400) is treated as permanent for this engine.","triggerScenarios":"Handle() gets a non-200 status: typically 403 when Cloudflare blocks the mimicked browser request, or 400 from an API change; 429/5xx instead return the Retryable branch.","commonSituations":"Cloudflare hard-blocks the datacenter/container IP (403), Sploitus changes its API path/contract, or the request payload becomes invalid after a refactor.","solutions":["Log/inspect the actual status code in the wrapped error","For 403: change egress IP or verify the Chrome-mimicking headers still match current Cloudflare expectations","For 400/404: compare the request body and sploitusAPIURL against the current Sploitus API contract and update the searcher","Rely on web_search fallback engines until Sploitus is reachable again"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"if resp.StatusCode != http.StatusOK {\n    // Non-retryable statuses (403 Cloudflare, 400) — switch engine\n    return \"\", Fatal(fmt.Errorf(\"Sploitus API returned HTTP %d\", resp.StatusCode))\n}","preventionTips":["Keep browser-mimicking headers in sync with current Cloudflare expectations","Verify the API endpoint/contract after any Sploitus change","Maintain alternate engines (e.g. other exploit searchers) for automatic failover","Log full status + a body snippet for fast triage of 403/400 responses"],"tags":["http-status","cloudflare","sploitus"],"backgroundTag":"unexpected-http-status","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}