getsentry / sentry-python

The official Python SDK for Sentry.io
https://sentry.io/for/python/
MIT License
1.86k stars 483 forks source link

422 is not reported despite setting `failed_request_status_codes` #3296

Open sentrivana opened 1 month ago

sentrivana commented 1 month ago

How do you use Sentry?

Sentry Saas (sentry.io)

Version

2.9.0

Steps to Reproduce

From Discord:

Using Sentry with FastAPI, I'm initializing Sentry as follows:

failed_request_status_codes = [range(400, 600)]
sentry_sdk.init(
    integrations=[
        StarletteIntegration(failed_request_status_codes=failed_request_status_codes),
        FastApiIntegration(failed_request_status_codes=failed_request_status_codes),
    ],
    before_send=filter_transactions,
)

HTTPException raised directly or unexpected 500 errors are well reported to Sentry. However, 422 errors, where the request doesn't match the expected type, are not being sent to Sentry. How can I resolve this?

Expected Result

422s should be reported.

Actual Result

422s are not reported.

antonpirker commented 1 month ago

I did some digging.

This is the check if the error is in the range of error that should be captured: https://github.com/getsentry/sentry-python/blob/master/sentry_sdk/integrations/starlette.py#L222

In there we do hasattr(exp, "status_code").

In the case of a HTTP 422 exp is RequestValidationError([{'type': 'missing', 'loc': ('query', 'user'), 'msg': 'Field required', 'input': None, 'url': 'https://errors.pydantic.dev/2.8/v/missing'}]) which does not have a status_code

(in comparison if it is a HTTP 405 it is HTTPException(status_code=405, detail='Method Not Allowed'))

It is not an HTTPException but an ValidationError.

To capture this validation error we need to monkey patch another part of FastAPI that is not the ExceptionMiddleware but rather this handler: https://github.com/tiangolo/fastapi/blob/15130a3eb5080d8d457752a502167ddd44d79156/fastapi/exception_handlers.py#L20-L26

antonpirker commented 1 month ago

Long story short: there is no easy fix for that :-)