Missing table name in IntegrityError (Django ORM) Missing table name in IntegrityError (Django ORM) postgresql postgresql

Missing table name in IntegrityError (Django ORM)


The exception message in this traceback is the original message from the database driver. It is useful to know this and the traceback if anything is googled, reported etc.

The exception class is the same django.db.utils.IntegrityError for all backends, but the message or rather arguments depend on the backend:

  • postgres: null value in column "manager_slug" violates not-null constraint\n DETAILS...\n
  • mysql . . : (1048, "Column 'manager_slug' cannot be null")
  • sqlite3 . : NOT NULL constraint failed: appname_modelname.manager_slug

The table name is visible only with sqlite3 backend. Some backends use only a string argument of exception, but mysql uses two arguments: a numeric error code and a message. (I like to accept that it is a general question, not only PostgreSQL.) Authors of some backends expect that the author of the app will know the table name directly or from SQL, but it is not true with general ORM packages. There is no preferable and generally acceptable way, how to extend the message even if it can be done technically perfect.

Development and debugging are easy:

  • Much additional information is available in DEBUG mode in development ("SQL" in the last frame or a class name of an object on a line like "myobj.save()")
  • python manage.py test --debug-sql: "Prints logged SQL queries on failure."
  • The same error in development/tests with sqlite3 is easier readable.

...but you are probably asking for a run-time error in production.

I guess about your possible intention in a so general question, what direction could be interesting for you.

A) The most important information from the traceback is usually a few lines above the many lines with ".../django/db/...". It is perfectly easy for a guru. It can be used very probably if the code is not so dynamic and general like a Django admin site, where no code near myobj.save() call (neither in parent frames) contains an explicit model name. Example:

# skip some initial universal code in ".../django/..."...# our apps start to be interesting... (maybe other installed app)...# START HERE: Open this line in the editor. If the function is universal, jump to the previous.File ".../me/app/...py", line 47, in my...  my_obj.save()# skip many stack frames .../django/db/... belowFile ".../django/db/models/base.py", line 734, in save  # self.save_base(...    # this line 733 is not visible      force_update=force_update, update_fields=update_fields)...# interesting only sql and params, but not visible in productionFile ".../django/db/backends/utils.py", line 64, in execute  return self.cursor.execute(sql, params)IntegrityError (or DataError similarly)...

B) Catch the information by a common ancestor of your models

class ...(models.Model):    def save(self, *args, **wkargs):        try:            super(..., self).save(*args, **wkargs)        except django.db.utils.IntegrityError as exc:            new_message = 'table {}'.format(self._meta.db_table)            exc.extra_info = new_message            # this is less compatible, but it doesn't require additional reading support            # exc.args = exc.args + (new_message,)            reraise

This could complicate debugging with multiple inheritance.

C) An implementation in Django db would be better, but I can not imagine that it will be accepted and not reverted after some issue.


if you can create sql function you can try:

create function to get last sequence value get_sequence_last_value (original post)

CREATE FUNCTION public.get_sequence_last_value(name) RETURNS int4 AS 'DECLAREls_sequence ALIAS FOR $1;lr_record RECORD;li_return INT4;BEGINFOR lr_record IN EXECUTE ''SELECT last_value FROM '' || ls_sequence LOOPli_return := lr_record.last_value;END LOOP;RETURN li_return;END;' LANGUAGE 'plpgsql' VOLATILE;

after it get table with sequence more then in error stack, and has column manager_slug

SELECT table_name, column_name FROM information_schema.columns WHERE table_name in (    SELECT table_name    FROM (        SELECT table_name,               get_sequence_last_value(                    substr(column_default, 10, strpos(column_default, '::regclass') - 11)                    ) as lv        FROM information_schema.columns         WHERE column_default LIKE 'nextval%'        ) as t_seq_lv    WHERE lv > 17485    )   AND column_name = 'manager_slug';

i understand that the solution not full, but any way i hope it can help you


I would suggest to use Sentry (https://sentry.io/welcome/). In Sentry Issues you can observe all local variables for all parts of a stack trace.screenshot of a sentry issue