mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 19:06:11 +00:00
Let an error body that is an array still be read
Google answers some failures with a JSON array holding the object every other provider sends on its own. _extract_error called .get() on it and raised AttributeError, which is not the ApiError every caller is holding, so a 503 from Google took the whole dictation down instead of pasting the raw transcript with the failure shown beside it. Found by dictating against a Google AI Studio outage: HTTP Error 503: Service Unavailable AttributeError: 'list' object has no attribute 'get' It runs while an exception is being raised, so it now ends in a string whatever arrives. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -262,10 +262,23 @@ def _request(url, data, headers, timeout=120, aborter=None):
|
||||
|
||||
|
||||
def _extract_error(body):
|
||||
"""The line worth showing out of a failed request's body.
|
||||
|
||||
Whatever comes back, this has to end in a string: it is called while an
|
||||
ApiError is being raised, and an exception thrown here would escape the
|
||||
`except ApiError` every caller is holding and lose the dictation the raw
|
||||
transcript would otherwise have been pasted from.
|
||||
"""
|
||||
try:
|
||||
payload = json.loads(body)
|
||||
except json.JSONDecodeError:
|
||||
return body[:300]
|
||||
if isinstance(payload, list):
|
||||
# Google answers some failures with an array holding the object the
|
||||
# other providers send on its own.
|
||||
payload = next((item for item in payload if isinstance(item, dict)), None)
|
||||
if not isinstance(payload, dict):
|
||||
return body[:300]
|
||||
err = payload.get("error")
|
||||
if isinstance(err, dict):
|
||||
return err.get("message") or json.dumps(err)[:300]
|
||||
|
||||
@@ -119,9 +119,22 @@ class ExtractError(unittest.TestCase):
|
||||
body = json.dumps({"error": {"code": 42}})
|
||||
self.assertIn("42", api._extract_error(body))
|
||||
|
||||
def test_an_error_wrapped_in_an_array(self):
|
||||
"""Google's 503 arrives this way, and .get() on a list raises."""
|
||||
body = json.dumps([{"error": {"code": 503,
|
||||
"message": "The model is overloaded."}}])
|
||||
self.assertEqual(api._extract_error(body), "The model is overloaded.")
|
||||
|
||||
def test_a_body_that_is_not_json(self):
|
||||
self.assertEqual(api._extract_error("<html>502</html>"), "<html>502</html>")
|
||||
|
||||
def test_no_shape_at_all_still_comes_back_as_a_string(self):
|
||||
"""It runs while an ApiError is being raised: throwing here would
|
||||
escape the `except ApiError` holding the raw transcript."""
|
||||
for body in ("[]", "[1, 2]", '"a string"', "null", "17"):
|
||||
with self.subTest(body=body):
|
||||
self.assertIsInstance(api._extract_error(body), str)
|
||||
|
||||
def test_a_wall_of_html_is_cut_short(self):
|
||||
self.assertEqual(len(api._extract_error("x" * 5000)), 300)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user