= Better Error Messages = Good error messages make for more productive developers. This page is a place to collect error messages that could stand improvement, or which are misleading or confusing in certain contexts. Most of us have had the experience of getting a "weird" message, puzzling it out (perhaps with help from django-users or #django) and then moving on. Some of these may seem like quick patches but others will take a bit of consideration -- that's why the wiki page rather than individual tickets. Some are more along the lines of "Django Lint" than simple changes to error output. For now, let's try dividing them into sections by major module. Within those sections suggested format is: error message, explanatory context (often important -- a message that is very helpful in one context can be confusing in another), suggested improvements/changes. Also see: * CommonPitfalls * NewbieMistakes == django.contrub.auth == If you try to create a model with a table name > 50 characters (and you've enabled django.contrib.auth) then you get a very poor error message when running syncdb. {{{ env src/tmp/qdel$ python ./manage.py syncdb Creating tables ... Traceback (most recent call last): ... ... django.db.utils.DatabaseError: value too long for type character varying(50) }}} '''Suggestion:''' Look for DatabaseError in contrib/auth/management/init.py. Related #18959 == django.core == The 404 error page served when django.core.urlresolvers.resolve() fails does not contain the exception stack trace, which makes finding the failing call unnecessarily difficult. * Ticket #22055 -- 404 page does not display stack trace when Resolver404 is raised from a view. * Ticket #21668 -- Invalid upload_to FileField attribute results in hard-to-debug "Bad Request" 400 error. * Ticket #22058 -- Add `Http405` exception class and `handler405` view (simillar to 404, 403 and 500). == django.core.urlresolver == Better error message when can't import url callback. Related #8809. == django.db == {{{ OperationalError: Unable to close due to unfinalised statements }}} '''Context:''' SQLite file permissions are incorrect (directory or DB file lack write permission)[[BR]] '''Suggestion:''' Check file permissions when running with SQLite backend and warn user if they seem incorrect {{{ ProgrammingError: ERROR: current transaction is aborted, commands ignored until end of transaction block }}} This pyscopg2 (PostgreSQL) error usually signifies that some ''previous'' database query was incorrect (e.g., you tried to {{{order_by()}}} a field that doesn't exist, or put a string in an integer column, etc.). That previous error aborted the transaction, causing all subsequent database access to fail with this message. If you get this while at a shell, you can fix your database connection by executing a rollback: {{{ from django.db import connection connection.cursor().execute('rollback') }}} If you get this from a view, it probably means the immediately previous query had a problem (but was caught by an over-eager exception handler). In certain situations with PostgreSQL, a bogus error message about SET TIME ZONE may be returned. See #3179 (which is closed, but has a description of the problem). The real error message can probably be found in the postgres log file. {{{ DoesNotExist: %s matching query does not exist }}} It would be really helpful for the error message to state what the query was, for example: {{{ raise self.model.DoesNotExist(("%s matching query does not exist " + "(query was: %s, %s)") % (self.model._meta.object_name, args, kwargs)) }}} If you create a ForeignKey with `blank=True`, but you don't specify `null=True`, and try to save the object without a value for the foreign key, you get this exception: {{{ ValueError: Cannot assign None: "Cat.home" does not allow null values. }}} You could argue that it's obvious, but it's confusing many people: * http://www.google.co.uk/search?gcx=c&sourceid=chrome&client=ubuntu&channel=cs&ie=UTF-8&q=%22Cannot+assign+None%3A%22+%22does+not+allow+null+values.%22 * http://stackoverflow.com/questions/4117345/django-null-foreignkey * http://stackoverflow.com/questions/1810745/django-cannot-assign-none-does-not-allow-null-values * http://groups.google.com/group/django-users/browse_thread/thread/af89c86e824cb0d8 * http://www.mail-archive.com/django-users@googlegroups.com/msg91776.html I think it would be a really good idea to make it really clear from the error message what you need to do (blank=True requires null=True on foreign key fields). Unfortunately we can't automatically fix it, because if the field is left blank, the developer might be intending to supply the value automatically before save (https://code.djangoproject.com/ticket/13824). Here are some tickets that must be paid attention to: * Raise explicit error when unpickling QuerySet from incompatible version. #21430 * Assigning unsaved model to a ForeignKey leads to silent failures. #10811 * #20752 * #7074 == django.forms == {{{ ValidationError: 'Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.' }}} If the error message contained the invalid data, and, especially the name of the field that was being validated, that would be way more helpful. Integrity Error is raised when trying to edit a model that has some unique_together fields and is registered with list_editable containing some of that fields. Related Ticket #13091. Ticket #15069 -- ValidationError message isn't helpful in tracking down the field that fails validation. == django.http == {{{ AttributeError: Http404 instance has no attribute 'has_header' }}} '''Context:''' Http404 is {{{return}}}ed instead of {{{raise}}}d[[BR]] '''Suggestion:''' Check type of HttpResponse before attempting to use (perhaps unPythonic?) or possibly give Http404 a clearer name like Http404Exception == django.shortcuts == Invoking .render() with a object instead of a HttpRequest as the first argument invokes AttributeError with the message: "'' object has no attribute 'META'". Better will be something like, "render() takes a request object for the first argument." == django.template == When resolving a template variable that calls an object method/property. If that method/property has errors we get a {{{VariableDoesNotExist}}} exception without what errors happened, which might confuse the user. See #16383 for more details. * See [http://groups.google.com/group/django-developers/browse_thread/thread/42aff5c291a69041/d006eb5292b8aac3 this thread on the django-developers list] for discussion of suppression of TypeError in the template engine. Looking at these might be useful: #6907 and #11421. == django.template.!__init!__.py == Using an invalid template tag results in the generic 'list index out of range' error which doesn't show any information about the offending file or expression. E.g., if a template contains: {{{ ... {% invalid_template_tag %} ... }}} An error occurs at line 279 of django.template.!__init!__.py: {{{ 278 try: 279 compiled_result = compile_func(self, token) 280 except KeyError: 281 self.invalid_block_tag(token, command) 282 except TemplateSyntaxError, e: 283 if not self.compile_function_error(token,e): 291 raise }}} What seems to be happening is that self.invalid_block_tag(...) raises an error which gets caught by !TemplateSyntaxError and which eventually leads to the generic 'list index out of range' error being reported in the Django error page.