Skip to content

Commit 0c820a7

Browse files
committed
fix(api): improve error handling for invalid JSON responses
- enhance `_get_error_message` to handle JSON decode errors - add detailed error message including the invalid response text - add tests covering valid JSON, invalid JSON, and non-JSON responses
1 parent 58df75e commit 0c820a7

2 files changed

Lines changed: 40 additions & 2 deletions

File tree

src/typesense/request_handler.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,11 @@ def _get_error_message(response: requests.Response) -> str:
260260
"""
261261
content_type = response.headers.get("Content-Type", "")
262262
if content_type.startswith("application/json"):
263-
err_message: str = response.json().get("message", "API error.")
264-
return err_message
263+
try:
264+
err_message: str = response.json().get("message", "API error.")
265+
return err_message
266+
except requests.exceptions.JSONDecodeError:
267+
return f"API error: Invalid JSON response: {response.text}"
265268
return "API error."
266269

267270
@staticmethod

tests/api_call_test.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,41 @@ def test_get_exception() -> None:
9494
assert RequestHandler._get_exception(999) == exceptions.TypesenseClientError
9595

9696

97+
def test_get_error_message_with_invalid_json() -> None:
98+
"""Test that it correctly handles invalid JSON in error responses."""
99+
response = requests.Response()
100+
response.headers["Content-Type"] = "application/json"
101+
response.status_code = 400
102+
# Set an invalid JSON string that would cause JSONDecodeError
103+
response._content = b'{"message": "Error occurred", "details": {"key": "value"'
104+
105+
error_message = RequestHandler._get_error_message(response)
106+
assert "API error: Invalid JSON response:" in error_message
107+
assert '{"message": "Error occurred", "details": {"key": "value"' in error_message
108+
109+
110+
def test_get_error_message_with_valid_json() -> None:
111+
"""Test that it correctly extracts error message from valid JSON responses."""
112+
response = requests.Response()
113+
response.headers["Content-Type"] = "application/json"
114+
response.status_code = 400
115+
response._content = b'{"message": "Error occurred", "details": {"key": "value"}}'
116+
117+
error_message = RequestHandler._get_error_message(response)
118+
assert error_message == "Error occurred"
119+
120+
121+
def test_get_error_message_with_non_json_content_type() -> None:
122+
"""Test that it returns a default error message for non-JSON content types."""
123+
response = requests.Response()
124+
response.headers["Content-Type"] = "text/plain"
125+
response.status_code = 400
126+
response._content = b'Not a JSON content'
127+
128+
error_message = RequestHandler._get_error_message(response)
129+
assert error_message == "API error."
130+
131+
97132
def test_normalize_params_with_booleans() -> None:
98133
"""Test that it correctly normalizes boolean values to strings."""
99134
parameter_dict: typing.Dict[str, str | bool] = {"key1": True, "key2": False}

0 commit comments

Comments
 (0)