fix(translate): handle invalid LLM JSON responses

This commit is contained in:
2026-07-15 20:06:39 +03:00
parent 612cc55911
commit 30c8acf7ae
4 changed files with 101 additions and 14 deletions

View File

@@ -19,6 +19,7 @@
# Only capath-based ssl.create_default_context() works with OpenSSL 3.x intermediates.
import asyncio
import json
import ssl
from typing import Any
@@ -115,7 +116,12 @@ def sanitize_url(url: str) -> str:
# @BRIEF Call OpenAI-compatible API asynchronously with rate-limit handling and structured output fallback.
# @PRE Valid API endpoint, key, model, and prompt.
# @POST Returns (response text, finish_reason).
# @RAISES ValueError when the provider returns an invalid JSON response body.
# @SIDE_EFFECT Async HTTP POST to LLM API with optional retry on 429.
# @RATIONALE Normalize malformed successful HTTP bodies into a stable provider error so
# preview and execution callers do not leak raw JSONDecodeError details.
# @REJECTED Letting response.json() propagate raw decode failures was rejected — it
# obscures the upstream failure and prevents callers from classifying the provider error.
# @REJECTED Keeping sync requests.post — would block async event loop during LLM calls.
# Per-request httpx.AsyncClient — loses connection pooling.
async def call_openai_compatible(
@@ -177,7 +183,20 @@ async def call_openai_compatible(
extra={"src": "SharedLlmHttpClient"},
)
response.raise_for_status()
data = response.json()
try:
data = response.json()
except (json.JSONDecodeError, ValueError) as exc:
logger.explore(
"LLM provider returned an invalid JSON response",
extra={
"src": "SharedLlmHttpClient",
"status_code": response.status_code,
"content_type": response.headers.get("content-type"),
"response_preview": (response_text or "")[:2000],
},
error=f"{type(exc).__name__}: {exc}",
)
raise ValueError("LLM provider returned an invalid JSON response") from exc
choices = data.get("choices", [])
if not choices: