[GH-ISSUE #1123] NOT NULL constraint failed: api_check.badge_key #780

Closed
opened 2026-02-25 23:43:33 +03:00 by kerem · 5 comments
Owner

Originally created by @fertek on GitHub (Feb 9, 2025).
Original GitHub issue: https://github.com/healthchecks/healthchecks/issues/1123

Hi,

I deployed the Healthchecks application (v3.9) on an Ubuntu 24.04.1 LTS server following https://healthchecks.io/docs/self_hosted/ (without Docker) and everything works fine. However, when I click on Add Check, fill out the form and click Save, I get a 500 error. In https://health.example.com/admin/logs/, the event is logged as follows:

Traceback (most recent call last):
File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 105, in _execute
return self.cursor.execute(sql, params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/db/backends/sqlite3/base.py", line 354, in execute
return super().execute(query, params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlite3.IntegrityError: NOT NULL constraint failed: api_check.badge_key

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File ".venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/views/decorators/http.py", line 64, in inner
return func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/contrib/auth/decorators.py", line 60, in _view_wrapper
return view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "hc/front/views.py", line 558, in add_check
check.save()
File ".venv/lib/python3.11/site-packages/django/db/models/base.py", line 892, in save
self.save_base(
File ".venv/lib/python3.11/site-packages/django/db/models/base.py", line 998, in save_base
updated = self._save_table(
^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/db/models/base.py", line 1161, in _save_table
results = self._do_insert(
^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/db/models/base.py", line 1202, in _do_insert
return manager._insert(
^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/db/models/query.py", line 1847, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1836, in execute_sql
cursor.execute(sql, params)
File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 79, in execute
return self._execute_with_wrappers(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers
return executor(sql, params, many, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 100, in _execute
with self.db.wrap_database_errors:
File ".venv/lib/python3.11/site-packages/django/db/utils.py", line 91, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 105, in _execute
return self.cursor.execute(sql, params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".venv/lib/python3.11/site-packages/django/db/backends/sqlite3/base.py", line 354, in execute
return super().execute(query, params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
django.db.utils.IntegrityError: NOT NULL constraint failed: api_check.badge_key

This is the content of the .env file:

SECRET_KEY='secret'
DEBUG=False

ALLOWED_HOSTS=health.example.com,localhost,127.0.0.1


EMAIL_HOST='live.smtp.mailtrap.io'
EMAIL_HOST_USER='api'
EMAIL_HOST_PASSWORD='secret'
EMAIL_PORT=587

EMAIL_USE_TLS=True
EMAIL_USE_SSL=False

EMAIL_USE_VERIFICATION=False
REGISTRATION_OPEN=False
SHELL_ENABLED=False

I use SQLite as database and all migrations have been applied via ./manage.py migrate.

Thanks for your help.

Originally created by @fertek on GitHub (Feb 9, 2025). Original GitHub issue: https://github.com/healthchecks/healthchecks/issues/1123 Hi, I deployed the Healthchecks application (`v3.9`) on an `Ubuntu 24.04.1 LTS` server following https://healthchecks.io/docs/self_hosted/ (without Docker) and everything works fine. However, when I click on `Add Check`, fill out the form and click `Save`, I get a 500 error. In https://health.example.com/admin/logs/, the event is logged as follows: ``` Traceback (most recent call last): File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 105, in _execute return self.cursor.execute(sql, params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/db/backends/sqlite3/base.py", line 354, in execute return super().execute(query, params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ sqlite3.IntegrityError: NOT NULL constraint failed: api_check.badge_key The above exception was the direct cause of the following exception: Traceback (most recent call last): File ".venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/views/decorators/http.py", line 64, in inner return func(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/contrib/auth/decorators.py", line 60, in _view_wrapper return view_func(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "hc/front/views.py", line 558, in add_check check.save() File ".venv/lib/python3.11/site-packages/django/db/models/base.py", line 892, in save self.save_base( File ".venv/lib/python3.11/site-packages/django/db/models/base.py", line 998, in save_base updated = self._save_table( ^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/db/models/base.py", line 1161, in _save_table results = self._do_insert( ^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/db/models/base.py", line 1202, in _do_insert return manager._insert( ^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/db/models/query.py", line 1847, in _insert return query.get_compiler(using=using).execute_sql(returning_fields) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1836, in execute_sql cursor.execute(sql, params) File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 79, in execute return self._execute_with_wrappers( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers return executor(sql, params, many, context) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 100, in _execute with self.db.wrap_database_errors: File ".venv/lib/python3.11/site-packages/django/db/utils.py", line 91, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File ".venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 105, in _execute return self.cursor.execute(sql, params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.11/site-packages/django/db/backends/sqlite3/base.py", line 354, in execute return super().execute(query, params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ django.db.utils.IntegrityError: NOT NULL constraint failed: api_check.badge_key ``` This is the content of the `.env` file: ``` SECRET_KEY='secret' DEBUG=False ALLOWED_HOSTS=health.example.com,localhost,127.0.0.1 EMAIL_HOST='live.smtp.mailtrap.io' EMAIL_HOST_USER='api' EMAIL_HOST_PASSWORD='secret' EMAIL_PORT=587 EMAIL_USE_TLS=True EMAIL_USE_SSL=False EMAIL_USE_VERIFICATION=False REGISTRATION_OPEN=False SHELL_ENABLED=False ``` I use SQLite as database and all migrations have been applied via `./manage.py migrate`. Thanks for your help.
kerem closed this issue 2026-02-25 23:43:33 +03:00
Author
Owner

@cuu508 commented on GitHub (Feb 9, 2025):

Thanks for the report.

I added the NOT NULL constraint on December 27, but released the v3.9 on December 20. Did you perhaps run a git master version or a nightly image at some point with the same database? If you backup and remove the database file, and run the migrations again to create a fresh database, can you still reproduce the problem?

<!-- gh-comment-id:2646327490 --> @cuu508 commented on GitHub (Feb 9, 2025): Thanks for the report. I added the NOT NULL constraint on December 27, but released the v3.9 on December 20. Did you perhaps run a git master version or a nightly image at some point with the same database? If you backup and remove the database file, and run the migrations again to create a fresh database, can you still reproduce the problem?
Author
Owner

@fertek commented on GitHub (Feb 9, 2025):

Thanks for the lightning-fast response, that was it! After git clone ... I did git checkout v3.9.

So git checkout master and systemctl restart healthchecks.service fixed the error, and I can create new Checks now.

<!-- gh-comment-id:2646402282 --> @fertek commented on GitHub (Feb 9, 2025): Thanks for the lightning-fast response, that was it! After `git clone ...` I did `git checkout v3.9`. So `git checkout master` and `systemctl restart healthchecks.service` fixed the error, and I can create new Checks now.
Author
Owner

@Marcool04 commented on GitHub (Jan 24, 2026):

I think I have managed to get myself in a similar type of situation. As we discussed previously in another issue https://github.com/healthchecks/healthchecks/issues/1231 I must have run 3.10 for a time, and now I am back on the latest available packaged 3.9 (on Arch Linux, held back waiting for Django to be updated), but when I try to add a new channel, I get this error:

Traceback (most recent call last):
  File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 105, in _execute
    return self.cursor.execute(sql, params)
           ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/lib/python3.14/site-packages/django/db/backends/sqlite3/base.py", line 354, in execute
    return super().execute(query, params)
           ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
sqlite3.IntegrityError: NOT NULL constraint failed: api_check.badge_key

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/lib/python3.14/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/lib/python3.14/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python3.14/site-packages/django/views/decorators/http.py", line 64, in inner
    return func(request, *args, **kwargs)
  File "/usr/lib/python3.14/site-packages/django/contrib/auth/decorators.py", line 60, in _view_wrapper
    return view_func(request, *args, **kwargs)
  File "/usr/share/webapps/healthchecks/hc/front/views.py", line 558, in add_check
    check.save()
    ~~~~~~~~~~^^
  File "/usr/lib/python3.14/site-packages/django/db/models/base.py", line 892, in save
    self.save_base(
    ~~~~~~~~~~~~~~^
        using=using,
        ^^^^^^^^^^^^
    ...<2 lines>...
        update_fields=update_fields,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/lib/python3.14/site-packages/django/db/models/base.py", line 998, in save_base
    updated = self._save_table(
        raw,
    ...<4 lines>...
        update_fields,
    )
  File "/usr/lib/python3.14/site-packages/django/db/models/base.py", line 1161, in _save_table
    results = self._do_insert(
        cls._base_manager, using, fields, returning_fields, raw
    )
  File "/usr/lib/python3.14/site-packages/django/db/models/base.py", line 1202, in _do_insert
    return manager._insert(
           ~~~~~~~~~~~~~~~^
        [self],
        ^^^^^^^
    ...<3 lines>...
        raw=raw,
        ^^^^^^^^
    )
    ^
  File "/usr/lib/python3.14/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/site-packages/django/db/models/query.py", line 1852, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/site-packages/django/db/models/sql/compiler.py", line 1836, in execute_sql
    cursor.execute(sql, params)
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 79, in execute
    return self._execute_with_wrappers(
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        sql, params, many=False, executor=self._execute
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 100, in _execute
    with self.db.wrap_database_errors:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 105, in _execute
    return self.cursor.execute(sql, params)
           ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/lib/python3.14/site-packages/django/db/backends/sqlite3/base.py", line 354, in execute
    return super().execute(query, params)
           ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
django.db.utils.IntegrityError: NOT NULL constraint failed: api_check.badge_key

I wonder if there is any relatively simple way for me to fix this hc.sqlite file which I appear to have damaged somehow, most likely by running a more recent version, then going back? As you said, with a clean, new database, the problem just goes away. But as I have quite a few checks which took a while to set up and tune, I would like to ask if there is maybe a solution to not have to restart from scratch? I don't see a method to export / reimport checks is there? Or a way to migrate from an old sqlite db to a newer one? Otherwise I'd be happy to manually edit the sqlite file if it's a pretty simple fix to make?

Any help or suggestions would be much appreciated. Cheers, Mark.

<!-- gh-comment-id:3794188080 --> @Marcool04 commented on GitHub (Jan 24, 2026): I think I have managed to get myself in a similar type of situation. As we discussed previously in another issue https://github.com/healthchecks/healthchecks/issues/1231 I must have run 3.10 for a time, and now I am back on the latest available packaged 3.9 (on Arch Linux, held back waiting for Django to be updated), but when I try to add a new channel, I get this error: ``` Traceback (most recent call last): File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 105, in _execute return self.cursor.execute(sql, params) ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/django/db/backends/sqlite3/base.py", line 354, in execute return super().execute(query, params) ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^ sqlite3.IntegrityError: NOT NULL constraint failed: api_check.badge_key The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/lib/python3.14/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) File "/usr/lib/python3.14/site-packages/django/core/handlers/base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/usr/lib/python3.14/site-packages/django/views/decorators/http.py", line 64, in inner return func(request, *args, **kwargs) File "/usr/lib/python3.14/site-packages/django/contrib/auth/decorators.py", line 60, in _view_wrapper return view_func(request, *args, **kwargs) File "/usr/share/webapps/healthchecks/hc/front/views.py", line 558, in add_check check.save() ~~~~~~~~~~^^ File "/usr/lib/python3.14/site-packages/django/db/models/base.py", line 892, in save self.save_base( ~~~~~~~~~~~~~~^ using=using, ^^^^^^^^^^^^ ...<2 lines>... update_fields=update_fields, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) ^ File "/usr/lib/python3.14/site-packages/django/db/models/base.py", line 998, in save_base updated = self._save_table( raw, ...<4 lines>... update_fields, ) File "/usr/lib/python3.14/site-packages/django/db/models/base.py", line 1161, in _save_table results = self._do_insert( cls._base_manager, using, fields, returning_fields, raw ) File "/usr/lib/python3.14/site-packages/django/db/models/base.py", line 1202, in _do_insert return manager._insert( ~~~~~~~~~~~~~~~^ [self], ^^^^^^^ ...<3 lines>... raw=raw, ^^^^^^^^ ) ^ File "/usr/lib/python3.14/site-packages/django/db/models/manager.py", line 87, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/django/db/models/query.py", line 1852, in _insert return query.get_compiler(using=using).execute_sql(returning_fields) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/django/db/models/sql/compiler.py", line 1836, in execute_sql cursor.execute(sql, params) ~~~~~~~~~~~~~~^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 79, in execute return self._execute_with_wrappers( ~~~~~~~~~~~~~~~~~~~~~~~~~~~^ sql, params, many=False, executor=self._execute ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) ^ File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers return executor(sql, params, many, context) File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 100, in _execute with self.db.wrap_database_errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/django/db/utils.py", line 91, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/usr/lib/python3.14/site-packages/django/db/backends/utils.py", line 105, in _execute return self.cursor.execute(sql, params) ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/django/db/backends/sqlite3/base.py", line 354, in execute return super().execute(query, params) ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^ django.db.utils.IntegrityError: NOT NULL constraint failed: api_check.badge_key ``` I wonder if there is any relatively simple way for me to fix this hc.sqlite file which I appear to have damaged somehow, most likely by running a more recent version, then going back? As you said, with a clean, new database, the problem just goes away. But as I have quite a few checks which took a while to set up and tune, I would like to ask if there is maybe a solution to not have to restart from scratch? I don't see a method to export / reimport checks is there? Or a way to migrate from an old sqlite db to a newer one? Otherwise I'd be happy to manually edit the sqlite file if it's a pretty simple fix to make? Any help or suggestions would be much appreciated. Cheers, Mark.
Author
Owner

@cuu508 commented on GitHub (Jan 25, 2026):

The safest way would be to use Django's manage.py migrate command to reverse the database migrations that came after 3.9. The command to do this would be:

python3 manage.py migrate api 0115_flip_api_flip_owner_created

(0115_flip_api_flip_owner_created was the last migration before the v3.9 release).

This command needs to be run on the more recent Healthchecks codebase you were running before (3.10?). It will not work on 3.9 – the migrations you need to reverse don't yet exist in 3.9.

In any case, make a copy of the sqlite file and keep it safe in case anything goes wrong.

<!-- gh-comment-id:3796213371 --> @cuu508 commented on GitHub (Jan 25, 2026): The safest way would be to use Django's `manage.py migrate` command to reverse the database migrations that came after 3.9. The command to do this would be: ``` python3 manage.py migrate api 0115_flip_api_flip_owner_created ``` (`0115_flip_api_flip_owner_created` was the last migration before the v3.9 release). This command needs to be run on the more recent Healthchecks codebase you were running before (3.10?). It will not work on 3.9 – the migrations you need to reverse don't yet exist in 3.9. In any case, make a copy of the sqlite file and keep it safe in case anything goes wrong.
Author
Owner

@Marcool04 commented on GitHub (Jan 25, 2026):

Wow! Amazing, that worked just fine! Thank you so so much for your amazing support for this really useful tool 🙏

<!-- gh-comment-id:3796392371 --> @Marcool04 commented on GitHub (Jan 25, 2026): Wow! Amazing, that worked just fine! Thank you so so much for your amazing support for this really useful tool 🙏
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/healthchecks#780
No description provided.