Skip to content

Commit 2b3b82d

Browse files
authored
fix: Handle JSONDecodeError gracefully in StarletteRequestExtractor (#4226)
Previously, when encountering malformed JSON in request bodies, the json() method would raise a JSONDecodeError. This change updates the method to catch the exception and return None instead, providing more consistent behavior and preventing unexpected crashes. Added a test case to verify this error handling behavior.
1 parent 5f71872 commit 2b3b82d

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

sentry_sdk/integrations/starlette.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import warnings
44
from collections.abc import Set
55
from copy import deepcopy
6+
from json import JSONDecodeError
67

78
import sentry_sdk
89
from sentry_sdk.consts import OP
@@ -680,8 +681,10 @@ async def json(self):
680681
# type: (StarletteRequestExtractor) -> Optional[Dict[str, Any]]
681682
if not self.is_json():
682683
return None
683-
684-
return await self.request.json()
684+
try:
685+
return await self.request.json()
686+
except JSONDecodeError:
687+
return None
685688

686689

687690
def _transaction_name_from_router(scope):

tests/integrations/starlette/test_starlette.py

+25
Original file line numberDiff line numberDiff line change
@@ -1354,3 +1354,28 @@ async def _error(_):
13541354
client.get("/error")
13551355

13561356
assert len(events) == int(expected_error)
1357+
1358+
1359+
@pytest.mark.asyncio
1360+
async def test_starletterequestextractor_malformed_json_error_handling(sentry_init):
1361+
scope = SCOPE.copy()
1362+
scope["headers"] = [
1363+
[b"content-type", b"application/json"],
1364+
]
1365+
starlette_request = starlette.requests.Request(scope)
1366+
1367+
malformed_json = "{invalid json"
1368+
malformed_messages = [
1369+
{"type": "http.request", "body": malformed_json.encode("utf-8")},
1370+
{"type": "http.disconnect"},
1371+
]
1372+
1373+
side_effect = [_mock_receive(msg) for msg in malformed_messages]
1374+
starlette_request._receive = mock.Mock(side_effect=side_effect)
1375+
1376+
extractor = StarletteRequestExtractor(starlette_request)
1377+
1378+
assert extractor.is_json()
1379+
1380+
result = await extractor.json()
1381+
assert result is None

0 commit comments

Comments
 (0)