{"record":{"id":"3547f8344897556c","repo":"BerriAI/litellm","slug":"failed-to-parse-response-raw-response-text","errorCode":null,"errorMessage":"Failed to parse response: {raw_response.text}","messagePattern":"Failed to parse response: (.+?)","errorType":"exception","errorClass":"VoyageError","httpStatus":null,"severity":"error","filePath":"litellm/llms/voyage/rerank/transformation.py","lineNumber":98,"sourceCode":"        self,\n        model: str,\n        raw_response: httpx.Response,\n        model_response: RerankResponse,\n        logging_obj: LiteLLMLoggingObj,\n        api_key: str | None = None,\n        request_data: dict = {},\n        optional_params: dict = {},\n        litellm_params: dict = {},\n    ) -> RerankResponse:\n        if raw_response.status_code != 200:\n            raise VoyageError(message=raw_response.text, status_code=raw_response.status_code)\n\n        logging_obj.post_call(original_response=raw_response.text)\n\n        try:\n            _json_response: Final = raw_response.json()\n        except Exception:\n            raise VoyageError(\n                message=f\"Failed to parse response: {raw_response.text}\",\n                status_code=raw_response.status_code,\n            )\n\n        # Voyage AI returns results in \"data\" key, not \"results\"\n        _results: Final[list[dict] | None] = _json_response.get(\"data\")\n        if _results is None:\n            raise ValueError(f\"No results found in the response={_json_response}\")\n\n        # Transform to LiteLLM format\n        transformed_results: Final = []\n        for result in _results:\n            transformed_result: dict[str, Any] = {\n                \"index\": result[\"index\"],\n                \"relevance_score\": result[\"relevance_score\"],\n            }\n            if \"document\" in result:\n                if isinstance(result[\"document\"], str):","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/voyage/rerank/transformation.py#L80-L116","documentation":"In VoyageRerankConfig.transform_rerank_response, non-200 statuses raise VoyageError first; for a 200 whose body still fails raw_response.json(), this VoyageError('Failed to parse response: ...') is raised with the raw text embedded. Typical causes: an HTML/empty body from a proxy or gateway, a truncated stream, or a non-JSON success response.","triggerScenarios":"litellm.rerank(model=\"voyage/voyage-3-rerank\", query=..., documents=[...]) routed through a corporate proxy that rewrites responses; intermittent truncated bodies on long document lists; a misconfigured api_base serving a landing page with 200 status.","commonSituations":"Self-hosted gateways in front of api.voyageai.com; retry storms producing gateway interstitials; debugging without verbose logs so the embedded raw text is missed; rate-limiter middlewares returning empty 200s.","solutions":["Read the embedded raw text in the exception message to see what the server actually returned.","curl -sS https://api.voyageai.com/v1/rerank -H 'Authorization: Bearer $VOYAGE_API_KEY' ... to confirm the endpoint returns JSON directly.","Remove or bypass HTTP(S)_PROXY for the Voyage host; add proxy exceptions.","Retry on this specific error - truncated/interstitial bodies are often transient."],"exampleFix":"# before (no handling; proxy sometimes returns HTML with 200)\nresult = litellm.rerank(model=\"voyage/voyage-3-rerank\", query=q, documents=docs)\n\n# after (retry on parse failure)\nfrom litellm.llms.voyage.common_utils import VoyageError\n\nfor attempt in range(3):\n    try:\n        result = litellm.rerank(model=\"voyage/voyage-3-rerank\", query=q, documents=docs)\n        break\n    except VoyageError as e:\n        if attempt == 2 or not str(e).startswith(\"Failed to parse response\"):\n            raise","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"from tenacity import retry, retry_if_exception, stop_after_attempt, wait_exponential\nfrom litellm.llms.voyage.common_utils import VoyageError\n\ndef _is_parse_error(e: Exception) -> bool:\n    return isinstance(e, VoyageError) and str(e).startswith(\"Failed to parse response\")\n\n@retry(retry=retry_if_exception(_is_parse_error), stop=stop_after_attempt(3), wait=wait_exponential(1, 2, 10))\ndef voyage_rerank(query: str, documents: list[str]):\n    return litellm.rerank(model=\"voyage/voyage-3-rerank\", query=query, documents=documents)","preventionTips":["Keep requests below proxy body-size limits by chunking large document lists.","Add proxy bypass rules for api.voyageai.com where policies allow.","Log the raw text embedded in the error to distinguish proxies from API changes."],"tags":["voyage","rerank","json-parse","response-parsing","litellm"],"backgroundTag":"invalid-json-response","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}