upgrade.sh Fails with "issubclass() arg 1 must be a class" #1060

Closed
opened 2026-04-05 20:07:21 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @didorothy on 10/15/2025

NetBox Edition

NetBox Community

NetBox Version

v4.4.3 (I'm actually running on the latest main branch in the repository)

Python Version

3.12

Steps to Reproduce

On an existing installation, run the upgrade.sh script and it throws the following exception:

... more above that is probably irrelevant ...
Finished.
Building documentation (mkdocs build)...
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: /home/ddorothy/apps/netbox.site/netbox/netbox/project-static/docs
INFO    -  Doc file 'development/models.md' contains a link '../features/customization.md#bookmarks', but the doc
           'features/customization.md' does not contain an anchor '#bookmarks'.
INFO    -  Documentation built in 8.74 seconds
Collecting static files (python3 netbox/manage.py collectstatic --no-input)...

416 static files copied to '/home/ddorothy/apps/netbox.site/netbox/netbox/static', 93 unmodified.
Removing stale content types (python3 netbox/manage.py remove_stale_contenttypes --no-input)...
No active configuration revision found - falling back to most recent
Traceback (most recent call last):
  File "/home/ddorothy/apps/netbox.site/netbox/netbox/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/core/management/base.py", line 416, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/core/management/base.py", line 460, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py", line 102, in handle
    ct.delete()
  File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/db/models/base.py", line 1281, in delete
    return collector.delete()
           ^^^^^^^^^^^^^^^^^^
  File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/db/models/deletion.py", line 458, in delete
    signals.pre_delete.send(
  File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/dispatch/dispatcher.py", line 189, in send
    response = receiver(signal=self, sender=sender, **named)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ddorothy/apps/netbox.site/netbox/netbox/extras/signals.py", line 152, in notify_object_changed
    if not has_feature(instance, 'notifications'):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ddorothy/apps/netbox.site/netbox/netbox/netbox/models/features.py", line 684, in has_feature
    return test_func(model)
           ^^^^^^^^^^^^^^^^
  File "/home/ddorothy/apps/netbox.site/netbox/netbox/netbox/models/features.py", line 643, in <lambda>
    register_model_feature('notifications', lambda model: issubclass(model, NotificationsMixin))
                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: issubclass() arg 1 must be a class

Expected Behavior

The upgrade.sh script should not throw an exception. I would expect if it was a problem with my installation it would give a different error message.

Observed Behavior

A TypeError was raised appearing to originate from line 152 in netbox/netbox/extras/signals.py

I bypassed the issue on my local copy by making the following change to that file:

diff --git a/netbox/extras/signals.py b/netbox/extras/signals.py
index 7105c38b4..39264201c 100644
--- a/netbox/extras/signals.py
+++ b/netbox/extras/signals.py
@@ -149,7 +149,7 @@ def notify_object_changed(sender, instance, **kwargs):
         event_type = OBJECT_DELETED

     # Skip unsupported object types
-    if not has_feature(instance, 'notifications'):
+    if not has_feature(instance.__class__, 'notifications'):
         return

     ct = ContentType.objects.get_for_model(instance)

Whether this is the right place for a change, I'm not sure but it seemed the easiest way to fix the problem.

*Originally created by @didorothy on 10/15/2025* ### NetBox Edition NetBox Community ### NetBox Version v4.4.3 (I'm actually running on the latest main branch in the repository) ### Python Version 3.12 ### Steps to Reproduce On an existing installation, run the upgrade.sh script and it throws the following exception: ``` ... more above that is probably irrelevant ... Finished. Building documentation (mkdocs build)... INFO - Cleaning site directory INFO - Building documentation to directory: /home/ddorothy/apps/netbox.site/netbox/netbox/project-static/docs INFO - Doc file 'development/models.md' contains a link '../features/customization.md#bookmarks', but the doc 'features/customization.md' does not contain an anchor '#bookmarks'. INFO - Documentation built in 8.74 seconds Collecting static files (python3 netbox/manage.py collectstatic --no-input)... 416 static files copied to '/home/ddorothy/apps/netbox.site/netbox/netbox/static', 93 unmodified. Removing stale content types (python3 netbox/manage.py remove_stale_contenttypes --no-input)... No active configuration revision found - falling back to most recent Traceback (most recent call last): File "/home/ddorothy/apps/netbox.site/netbox/netbox/manage.py", line 10, in <module> execute_from_command_line(sys.argv) File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/core/management/base.py", line 416, in run_from_argv self.execute(*args, **cmd_options) File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/core/management/base.py", line 460, in execute output = self.handle(*args, **options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py", line 102, in handle ct.delete() File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/db/models/base.py", line 1281, in delete return collector.delete() ^^^^^^^^^^^^^^^^^^ File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/db/models/deletion.py", line 458, in delete signals.pre_delete.send( File "/home/ddorothy/apps/netbox.site/netbox/venv/lib/python3.12/site-packages/django/dispatch/dispatcher.py", line 189, in send response = receiver(signal=self, sender=sender, **named) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/ddorothy/apps/netbox.site/netbox/netbox/extras/signals.py", line 152, in notify_object_changed if not has_feature(instance, 'notifications'): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/ddorothy/apps/netbox.site/netbox/netbox/netbox/models/features.py", line 684, in has_feature return test_func(model) ^^^^^^^^^^^^^^^^ File "/home/ddorothy/apps/netbox.site/netbox/netbox/netbox/models/features.py", line 643, in <lambda> register_model_feature('notifications', lambda model: issubclass(model, NotificationsMixin)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: issubclass() arg 1 must be a class ``` ### Expected Behavior The upgrade.sh script should not throw an exception. I would expect if it was a problem with my installation it would give a different error message. ### Observed Behavior A TypeError was raised appearing to originate from line [152 in netbox/netbox/extras/signals.py](https://github.com/netbox-community/netbox/blob/main/netbox/extras/signals.py#L152) I bypassed the issue on my local copy by making the following change to that file: ``` diff --git a/netbox/extras/signals.py b/netbox/extras/signals.py index 7105c38b4..39264201c 100644 --- a/netbox/extras/signals.py +++ b/netbox/extras/signals.py @@ -149,7 +149,7 @@ def notify_object_changed(sender, instance, **kwargs): event_type = OBJECT_DELETED # Skip unsupported object types - if not has_feature(instance, 'notifications'): + if not has_feature(instance.__class__, 'notifications'): return ct = ContentType.objects.get_for_model(instance) ``` Whether this is the right place for a change, I'm not sure but it seemed the easiest way to fix the problem.
MrUnknownDE added the type: bugseverity: highstatus: acceptedtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugseverity: highstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: accepted labels 2026-04-05 20:08:08 +02:00
Sign in to join this conversation.
No Label severity: high severity: high status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#1060