Upgrade failure while removing stale content types #10185

Closed
opened 2025-12-29 21:27:55 +01:00 by adam · 7 comments
Owner

Originally created by @mjf on GitHub (Sep 4, 2024).

Deployment Type

Self-hosted

NetBox Version

v4.1.0

Python Version

3.11

Steps to Reproduce

  1. have Netbox DNS plugin installed (and fully utilized with at least some sample data)
  2. upgrade NetBox as usual (via PYTHON=python3.11 ./upgrade.sh)

Expected Behavior

No failure and stale content correctly removed.

Observed Behavior

Removing stale content types (python3 netbox/manage.py remove_stale_contenttypes --no-input)...
Traceback (most recent call last):
  File "/opt/netbox-4.1.0/netbox/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/core/management/base.py", line 413, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/core/management/base.py", line 459, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py", line 101, in handle
    ct.delete()
  File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/db/models/base.py", line 1182, in delete
    collector.collect([self], keep_parents=keep_parents)
  File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/db/models/deletion.py", line 355, in collect
    raise ProtectedError(
django.db.models.deletion.ProtectedError: ("Cannot delete some instances of model 'ContentType' because they are referenced through protected foreign keys: 'ObjectChange.changed_object_type'.", {<ObjectChange: contact SOME-IDENTIFIER (Some Name) created by redacted@example.com>})

The SOME-IDENTIFIER, Some Name and even the user (who created the object) are quite of no use when I tried to look it up in the Postgres database. I can for sure remove the dependent object manually from the database which may help this script to proceed, but I have no idea what table this comes from and I do not python, sorry for that. All I can say is that the original IDENTIFIER (redacted in the error above) suggests it has something to do with the NetBox DNS plugin and it's "Registration Contacts" identities.

Originally created by @mjf on GitHub (Sep 4, 2024). ### Deployment Type Self-hosted ### NetBox Version v4.1.0 ### Python Version 3.11 ### Steps to Reproduce 1. have Netbox DNS plugin installed (and fully utilized with at least some sample data) 2. upgrade NetBox as usual (via `PYTHON=python3.11 ./upgrade.sh`) ### Expected Behavior No failure and stale content correctly removed. ### Observed Behavior ```python Removing stale content types (python3 netbox/manage.py remove_stale_contenttypes --no-input)... Traceback (most recent call last): File "/opt/netbox-4.1.0/netbox/manage.py", line 10, in <module> execute_from_command_line(sys.argv) File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/core/management/base.py", line 413, in run_from_argv self.execute(*args, **cmd_options) File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/core/management/base.py", line 459, in execute output = self.handle(*args, **options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py", line 101, in handle ct.delete() File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/db/models/base.py", line 1182, in delete collector.collect([self], keep_parents=keep_parents) File "/opt/netbox-4.1.0/venv/lib/python3.11/site-packages/django/db/models/deletion.py", line 355, in collect raise ProtectedError( django.db.models.deletion.ProtectedError: ("Cannot delete some instances of model 'ContentType' because they are referenced through protected foreign keys: 'ObjectChange.changed_object_type'.", {<ObjectChange: contact SOME-IDENTIFIER (Some Name) created by redacted@example.com>}) ``` The `SOME-IDENTIFIER`, `Some Name` and even the user (who created the object) are quite of no use when I tried to look it up in the Postgres database. I can for sure remove the dependent object manually from the database which may help this script to proceed, but I have no idea what table this comes from and I do not python, sorry for that. All I can say is that the original `IDENTIFIER` (redacted in the error above) suggests it has something to do with the NetBox DNS plugin and it's "Registration Contacts" identities.
adam closed this issue 2025-12-29 21:27:55 +01:00
Author
Owner

@jeremystretch commented on GitHub (Sep 4, 2024):

I'm not sure what, if any, fix this requires. remove_stale_contenttypes is a stock Django management command which automatically deletes the ContentType records for models which have been removed. Its documentation states:

Any objects that depend on the deleted content types will also be deleted.

However, records which maintain non-nullable generic foreign key relationships to these objects (e.g. ObjectChange records) prevent this as it would invalidate those relationships.

One workaround is to manually delete all change records associated with the specific model(s) being removed. Alternatively, it may be acceptable to simply ignore the stale content types.

@jeremystretch commented on GitHub (Sep 4, 2024): I'm not sure what, if any, fix this requires. `remove_stale_contenttypes` is a [stock Django management command](https://docs.djangoproject.com/en/5.1/ref/django-admin/#remove-stale-contenttypes) which automatically deletes the ContentType records for models which have been removed. Its documentation states: > Any objects that depend on the deleted content types will also be deleted. However, records which maintain non-nullable generic foreign key relationships to these objects (e.g. ObjectChange records) prevent this as it would invalidate those relationships. One workaround is to manually delete all change records associated with the specific model(s) being removed. Alternatively, it may be acceptable to simply ignore the stale content types.
Author
Owner

@peteeckel commented on GitHub (Sep 4, 2024):

The problem could be that a model was renamed in NetBox DNS between 1.0.7 and 1.1.0 (Contact became RegistrationContact).

I had exactly the same error and fixed it manually by removing the entries for the old model name from the ObjectChange table.

@peteeckel commented on GitHub (Sep 4, 2024): The problem could be that a model was renamed in NetBox DNS between 1.0.7 and 1.1.0 (`Contact` became `RegistrationContact`). I had exactly the same error and fixed it manually by removing the entries for the old model name from the `ObjectChange` table.
Author
Owner

@peteeckel commented on GitHub (Sep 4, 2024):

My solution was to find the ID for the old object type Contact and delete all entries for that type from core_objectchange:

DELETE FROM core_objectchange WHERE changed_object_type_id=(
    SELECT id FROM django_content_type WHERE app_label='netbox_dns' AND model='contact'
);
@peteeckel commented on GitHub (Sep 4, 2024): My solution was to find the ID for the old object type `Contact` and delete all entries for that type from `core_objectchange`: ``` DELETE FROM core_objectchange WHERE changed_object_type_id=( SELECT id FROM django_content_type WHERE app_label='netbox_dns' AND model='contact' ); ```
Author
Owner

@mjf commented on GitHub (Sep 5, 2024):

DELETE FROM core_objectchange WHERE changed_object_type_id=(
    SELECT id FROM django_content_type WHERE app_label='netbox_dns' AND model='contact'
);

That solved the issue. What to do next with this issue? Shall I reference it to the NetBox DNS project? I think they should provide at least some documentation on how to fix this or perhaps find some way it not to happen at all next time...

@mjf commented on GitHub (Sep 5, 2024): > ``` > DELETE FROM core_objectchange WHERE changed_object_type_id=( > SELECT id FROM django_content_type WHERE app_label='netbox_dns' AND model='contact' > ); > ``` That solved the issue. What to do next with this issue? Shall I reference it to the NetBox DNS project? I think they should provide at least some documentation on how to fix this or perhaps find some way it not to happen at all next time...
Author
Owner

@peteeckel commented on GitHub (Sep 5, 2024):

Hi @mjf, thanks for confirming that it worked for you, too.

It's a good question where the bug is actually rooted. The immediate cause was definitely the renaming of the model in NetBox DNS, but that's not such an uncommon process, the functionality that failed is pure Django and the ObjectChange
model, which is a NetBox specific model, also has some role in it.

I will modify the migration that renames the Contact to fix this issue for NetBox DNS, but I regard that as a workaround. Probably this will repeat in every other case where a plugin's models get renamed (there is nothing special about the Contact model in NetBox DNS), and there could also be a connection with recent changes in NetBox (e.g. #15277).

@peteeckel commented on GitHub (Sep 5, 2024): Hi @mjf, thanks for confirming that it worked for you, too. It's a good question where the bug is actually rooted. The immediate cause was definitely the renaming of the model in NetBox DNS, but that's not such an uncommon process, the functionality that failed is pure Django and the `ObjectChange` model, which is a NetBox specific model, also has some role in it. I will modify the migration that renames the `Contact` to fix this issue for NetBox DNS, but I regard that as a workaround. Probably this will repeat in every other case where a plugin's models get renamed (there is nothing special about the `Contact` model in NetBox DNS), and there could also be a connection with recent changes in NetBox (e.g. #15277).
Author
Owner

@peteeckel commented on GitHub (Sep 5, 2024):

I also referenced this in announcement https://github.com/peteeckel/netbox-plugin-dns/discussions/387 for documentation purposes.

@peteeckel commented on GitHub (Sep 5, 2024): I also referenced this in announcement https://github.com/peteeckel/netbox-plugin-dns/discussions/387 for documentation purposes.
Author
Owner

@jeremystretch commented on GitHub (Sep 5, 2024):

I'm going to close this out as it doesn't appear that any changes to NetBox itself are needed at this time.

@jeremystretch commented on GitHub (Sep 5, 2024): I'm going to close this out as it doesn't appear that any changes to NetBox itself are needed at this time.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#10185