{"record":{"id":"c43f656d164e51af","repo":"BerriAI/litellm","slug":"failed-to-parse-volcengine-response-as-json-e","errorCode":null,"errorMessage":"Failed to parse Volcengine response as JSON: {e}","messagePattern":"Failed to parse Volcengine response as JSON: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/volcengine/embedding/transformation.py","lineNumber":165,"sourceCode":"\n        return data\n\n    def transform_embedding_response(\n        self,\n        model: str,\n        raw_response: httpx.Response,\n        model_response: EmbeddingResponse,\n        logging_obj: LiteLLMLoggingObj,\n        api_key: str | None,\n        request_data: dict,\n        optional_params: dict,\n        litellm_params: dict,\n    ) -> EmbeddingResponse:\n        \"\"\"Transform Volcengine response to EmbeddingResponse\"\"\"\n        try:\n            response_json: Final = raw_response.json()\n        except Exception as e:\n            raise ValueError(f\"Failed to parse Volcengine response as JSON: {e}\")\n\n        # Volcengine response format matches OpenAI format closely\n        # Just need to ensure all required fields are present\n        transformed_response: Final = {\n            \"object\": \"list\",\n            \"data\": response_json.get(\"data\", []),\n            \"model\": response_json.get(\"model\", model),\n            \"usage\": response_json.get(\"usage\", {}),\n        }\n\n        # Add id if present\n        if \"id\" in response_json:\n            transformed_response[\"id\"] = response_json[\"id\"]\n\n        # Create EmbeddingResponse from transformed data\n        return EmbeddingResponse(**transformed_response)\n\n    def validate_environment(","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/volcengine/embedding/transformation.py#L147-L183","documentation":"After the HTTP call to Volcengine's embedding endpoint returns, the handler does raw_response.json(). If the body is not valid JSON (HTML error page, empty body, proxy interception, auth redirect), this ValueError wraps the parse exception. Note the status code is not checked before parsing here, so non-2xx responses with non-JSON bodies land in this branch.","triggerScenarios":"A corporate proxy or gateway returns an HTML block page; the Volcengine endpoint returns an XML/plain-text error (rate limit, WAF) instead of JSON; a wrong api_base pointing at a website; a truncated body from a dropped connection.","commonSituations":"Self-misconfigured api_base (e.g. missing /api/v3 so the server serves a landing page); Ark region endpoints changed; captive-portal/proxy environments; debugging with verbose logging disabled so the raw text is never seen.","solutions":["Enable litellm.set_verbose = True or check logging to capture raw_response.text and see what the server actually returned.","Verify the endpoint: it should resolve to https://ark.cn-beijing.volces.com/api/v3/embeddings or your custom base ending in /api/v3.","Check api_key validity - expired Ark keys can produce non-JSON auth errors from gateways.","Bypass/inspect proxies (HTTP_PROXY/HTTPS_PROXY) and confirm the raw response with curl."],"exampleFix":"# before\nresp = litellm.embedding(model=\"volcengine/ep-...\", input=[\"hi\"], api_base=\"https://ark.cn-beijing.volces.com\")\n# -> ValueError: Failed to parse Volcengine response as JSON ...\n\n# after\nresp = litellm.embedding(\n    model=\"volcengine/ep-...\",\n    input=[\"hi\"],\n    api_base=\"https://ark.cn-beijing.volces.com/api/v3\",  # correct base\n)","handlingStrategy":"try-catch","validationCode":"import socket\nfrom urllib.parse import urlparse\n\ndef endpoint_looks_right(api_base: str | None) -> bool:\n    base = api_base or \"https://ark.cn-beijing.volces.com/api/v3\"\n    p = urlparse(base)\n    return p.scheme in {\"http\", \"https\"} and p.netloc.endswith(\"volces.com\")\n\n# fast pre-flight only catches obviously wrong bases; non-JSON bodies still need try/catch","typeGuard":null,"tryCatchPattern":"try:\n    resp = litellm.embedding(model=\"volcengine/ep-...\", input=inputs)\nexcept ValueError as e:\n    if \"Failed to parse Volcengine response\" in str(e):\n        # log and retry once - proxies/WAFs often produce transient non-JSON bodies\n        logging.warning(\"non-JSON Volcengine body: %s\", e)\n        resp = litellm.embedding(model=\"volcengine/ep-...\", input=inputs)\n    else:\n        raise","preventionTips":["Pin api_base to the official https://ark.<region>.volces.com/api/v3 host.","Keep verbose logging available in staging so raw bodies can be inspected.","Whitelist ark.*.volces.com in corporate proxies and verify with curl after network changes."],"tags":["volcengine","embedding","json-parse","response-parsing","litellm"],"backgroundTag":"invalid-json-response","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}