#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 , 10 months ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:2 by , 10 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 , 10 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: do_something(json.loads(request.body.decode('utf-8'))['field_i_want'])
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?
comment:4 by , 10 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?
comment:5 by , 10 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.
follow-up: 7 comment:6 by , 10 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.
comment:7 by , 10 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.
follow-up: 9 comment:8 by , 10 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.
comment:9 by , 10 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 , 10 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.
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.