Opened 4 months ago

Closed 4 months ago

Last modified 4 months ago

#35098 closed Bug (invalid)

ValidationError is being converted into a 500 Internal Server Error response

Reported by: Yawar Quadir Amin Owned by:
Component: Error reporting Version: 5.0
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

If I raise a ValidationError in my app: https://docs.djangoproject.com/en/5.0/ref/exceptions/#validationerror

It is not explicitly handled by the function that converts exceptions into Django responses: https://github.com/django/django/blob/ecd3071dac9bc32028849b1563dc30e49744950e/django/core/handlers/exception.py#L63

So, the app is responding with a 500 Internal Server Error.

Expected behaviour is that it should respond with 400 Bad Request.

Change History (10)

comment:1 by Mariusz Felisiak, 4 months ago

Resolution: invalid
Status: newclosed

Exceptions are not converted to anything if you raise them at a random place in your app. If you're having trouble understanding how Django works, see TicketClosingReasons/UseSupportChannels for ways to get help.

comment:2 by Natalia Bidart, 4 months ago

Hello, thank you for your report and interest in making Django better. When you say:

Expected behaviour is that it should respond with 400 Bad Request.

What do you mean exactly? Django has historically had this behavior. If ValidationError is raised outside documented form clean methods, it'll get propagated so upper layers handle it, or they will end up as a 500 response (because this is really an unhandled error).

comment:3 by Yawar Quadir Amin, 4 months ago

Here's a simplified example. I have a views.py with:

# Obviously, this is used as a handler for a route in urls.py
def handle_foo(request: HttpRequest, **kwargs: dict[str, Any]) -> HttpResponse:
  txt = do_something(json.loads(request.body.decode('utf-8'))['field_i_want'])
  return JsonResponse({'ok': txt})

And I have do_something defined as:

def do_something(value: str):
  if bad(value): raise ValidationError('bad value')
  return f'good value: {value}'

Now I expect this to respond with a 400 Bad Request, but it responds with 500 Internal Server Error. And the traceback points to the function in Django Core which I linked earlier. It seems like this function is supposed to handle Django exceptions, so I'm wondering why it doesn't handle the ValidationException?

Last edited 4 months ago by Yawar Quadir Amin (previous) (diff)

comment:4 by Yawar Quadir Amin, 4 months ago

Exceptions are not converted to anything if you raise them at a random place in your app.

(a) It's not a random place, it's directly in the call stack of the URL route handler.

(b) Is this documented? I'm looking at the recommended best practices: https://docs.djangoproject.com/en/5.0/ref/forms/validation/#raising-validation-error

And it only shows you how to raise the error yourself. It doesn't say anything about raising it in a specific place?

Last edited 4 months ago by Yawar Quadir Amin (previous) (diff)

comment:5 by Mariusz Felisiak, 4 months ago

Again, Trac is not a support channel. If you're having trouble understanding how Django works, see TicketClosingReasons/UseSupportChannels for ways to get help.

comment:6 by Yawar Quadir Amin, 4 months ago

Hi, I am not interested in getting support. I can handle the error perfectly fine on my end. I am reporting what seems like an obvious bug with an easy fix. You're not interested, that's fine. I am good either way.

in reply to:  6 comment:7 by Natalia Bidart, 4 months ago

Replying to Yawar Quadir Amin:

Hi, I am not interested in getting support. I can handle the error perfectly fine on my end. I am reporting what seems like an obvious bug with an easy fix. You're not interested, that's fine. I am good either way.

We define support as understanding how Django operates and the expected patterns for use in your Django app. Numerous tutorials and documentation resources are available to guide you in encapsulating your app's business logic into specific modules and forms. It's important to note that failing to handle a ValidationError in your code will result in a 500 response, which is a standard behavior in Django and not a bug.

comment:8 by Yawar Quadir Amin, 4 months ago

Respectfully, a great place to document this would be https://docs.djangoproject.com/en/5.0/ref/exceptions/

Something like:

Django raises some of its own exceptions as well as standard Python exceptions. All exceptions cause a 500 Internal Server Error response if they reach the handler level, unless documented otherwise.

And then actually documenting the specific exceptions which are processed and return non-500 responses.

in reply to:  8 comment:9 by Mariusz Felisiak, 4 months ago

This is not a bug but a standard behavior not only for Django but for any framework or programming language. There is nothing to document. Personally, I'd recommend reaching support channels and trying to understand Django better before writing more code, but of course it's your choice. All the best.

comment:10 by Yawar Quadir Amin, 4 months ago

As I mentioned yesterday, I already solved the issue on my end with a couple lines of code changes. Thanks for your concern. I am happy to read any documentation but it seems there is nothing to document because this is a universal behaviour. Yet when I raise a RequestValidationError in a FastAPI handler, it is converted into a 422 Unprocessable Entity response.

Since this is fine, nothing further from my side. Thanks for your attention.

Note: See TracTickets for help on using tickets.
Back to Top