Netbox 3.1 upgrade breaks plugins #5743

Closed
opened 2025-12-29 19:32:06 +01:00 by adam · 1 comment
Owner

Originally created by @peteeckel on GitHub (Dec 8, 2021).

NetBox version

v3.1.0

Python version

3.8

Steps to Reproduce

Upgrade from Netbox 3.0.x to Netbox 3.1 with plugins installed that use the CustomFieldModelForm or CustomFieldForm classes.

Expected Behavior

After running the upgrade procedure, plugins should still be working.

Observed Behavior

Running the migration fails with a trace:

Traceback (most recent call last):
  File "/opt/netbox/netbox/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/base.py", line 393, in execute
    self.check()
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/base.py", line 419, in check
    all_issues = checks.run_checks(
  File "/opt/netbox/lib/python3.8/site-packages/django/core/checks/registry.py", line 76, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/checks/urls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/checks/urls.py", line 23, in check_resolver
    return check_method()
  File "/opt/netbox/lib/python3.8/site-packages/django/urls/resolvers.py", line 412, in check
    for pattern in self.url_patterns:
  File "/opt/netbox/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/opt/netbox/lib/python3.8/site-packages/django/urls/resolvers.py", line 598, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/opt/netbox/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/opt/netbox/lib/python3.8/site-packages/django/urls/resolvers.py", line 591, in urlconf_module
    return import_module(self.urlconf_name)
  File "/opt/netbox/lib64/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/opt/netbox/netbox/netbox/urls.py", line 9, in <module>
    from extras.plugins.urls import plugin_admin_patterns, plugin_patterns, plugin_api_patterns
  File "/opt/netbox/netbox/extras/plugins/urls.py", line 28, in <module>
    urlpatterns = import_object(f"{plugin_path}.urls.urlpatterns")
  File "/opt/netbox/netbox/extras/plugins/utils.py", line 31, in import_object
    spec.loader.exec_module(module)
  File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/urls.py", line 5, in <module>
    from .views import (
  File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/views.py", line 3, in <module>
    from netbox_dns.forms import (
  File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/forms.py", line 37, in <module>
    class ZoneForm(BootstrapMixin, CustomFieldModelForm):
  File "/opt/netbox/lib/python3.8/site-packages/django/forms/models.py", line 226, in __new__
    new_class = super().__new__(mcs, name, bases, attrs)
  File "/opt/netbox/lib/python3.8/site-packages/django/forms/forms.py", line 31, in __new__
    new_class = super().__new__(mcs, name, bases, attrs)
  File "/opt/netbox/lib/python3.8/site-packages/django/forms/widgets.py", line 191, in __new__
    new_class = super().__new__(mcs, name, bases, attrs)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases BootstrapMixin, CustomFieldModelForm

The reason is that CustomFieldForm and CustomFieldModelForm implicitly inherit from BootstrapMixin in 3.1, which they formerly didn't do. So classes defined in a plugin that explicitly inherit from BootstrapMixin break after the upgrade.

This creates a situation where a plugin is either compatible with Netbox 3.1 or with earlier versions, but not both.

Is it possible thta using the CustomField* classes is discouraged as their interface isn't supposed to be stable?

Originally created by @peteeckel on GitHub (Dec 8, 2021). ### NetBox version v3.1.0 ### Python version 3.8 ### Steps to Reproduce Upgrade from Netbox 3.0.x to Netbox 3.1 with plugins installed that use the CustomFieldModelForm or CustomFieldForm classes. ### Expected Behavior After running the upgrade procedure, plugins should still be working. ### Observed Behavior Running the migration fails with a trace: ``` Traceback (most recent call last): File "/opt/netbox/netbox/manage.py", line 10, in <module> execute_from_command_line(sys.argv) File "/opt/netbox/lib/python3.8/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line utility.execute() File "/opt/netbox/lib/python3.8/site-packages/django/core/management/__init__.py", line 413, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/opt/netbox/lib/python3.8/site-packages/django/core/management/base.py", line 354, in run_from_argv self.execute(*args, **cmd_options) File "/opt/netbox/lib/python3.8/site-packages/django/core/management/base.py", line 393, in execute self.check() File "/opt/netbox/lib/python3.8/site-packages/django/core/management/base.py", line 419, in check all_issues = checks.run_checks( File "/opt/netbox/lib/python3.8/site-packages/django/core/checks/registry.py", line 76, in run_checks new_errors = check(app_configs=app_configs, databases=databases) File "/opt/netbox/lib/python3.8/site-packages/django/core/checks/urls.py", line 13, in check_url_config return check_resolver(resolver) File "/opt/netbox/lib/python3.8/site-packages/django/core/checks/urls.py", line 23, in check_resolver return check_method() File "/opt/netbox/lib/python3.8/site-packages/django/urls/resolvers.py", line 412, in check for pattern in self.url_patterns: File "/opt/netbox/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/opt/netbox/lib/python3.8/site-packages/django/urls/resolvers.py", line 598, in url_patterns patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) File "/opt/netbox/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/opt/netbox/lib/python3.8/site-packages/django/urls/resolvers.py", line 591, in urlconf_module return import_module(self.urlconf_name) File "/opt/netbox/lib64/python3.8/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1014, in _gcd_import File "<frozen importlib._bootstrap>", line 991, in _find_and_load File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 671, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 783, in exec_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "/opt/netbox/netbox/netbox/urls.py", line 9, in <module> from extras.plugins.urls import plugin_admin_patterns, plugin_patterns, plugin_api_patterns File "/opt/netbox/netbox/extras/plugins/urls.py", line 28, in <module> urlpatterns = import_object(f"{plugin_path}.urls.urlpatterns") File "/opt/netbox/netbox/extras/plugins/utils.py", line 31, in import_object spec.loader.exec_module(module) File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/urls.py", line 5, in <module> from .views import ( File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/views.py", line 3, in <module> from netbox_dns.forms import ( File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/forms.py", line 37, in <module> class ZoneForm(BootstrapMixin, CustomFieldModelForm): File "/opt/netbox/lib/python3.8/site-packages/django/forms/models.py", line 226, in __new__ new_class = super().__new__(mcs, name, bases, attrs) File "/opt/netbox/lib/python3.8/site-packages/django/forms/forms.py", line 31, in __new__ new_class = super().__new__(mcs, name, bases, attrs) File "/opt/netbox/lib/python3.8/site-packages/django/forms/widgets.py", line 191, in __new__ new_class = super().__new__(mcs, name, bases, attrs) TypeError: Cannot create a consistent method resolution order (MRO) for bases BootstrapMixin, CustomFieldModelForm ``` The reason is that CustomFieldForm and CustomFieldModelForm implicitly inherit from BootstrapMixin in 3.1, which they formerly didn't do. So classes defined in a plugin that explicitly inherit from BootstrapMixin break after the upgrade. This creates a situation where a plugin is either compatible with Netbox 3.1 or with earlier versions, but not both. Is it possible thta using the CustomField* classes is discouraged as their interface isn't supposed to be stable?
adam added the type: bug label 2025-12-29 19:32:06 +01:00
adam closed this issue 2025-12-29 19:32:07 +01:00
Author
Owner

@jeremystretch commented on GitHub (Dec 8, 2021):

This is not a NetBox issue. Please see the plugins development documentation for a complete list of supported components. Any component of NetBox not on that list is not supported for use by plugins.

@jeremystretch commented on GitHub (Dec 8, 2021): This is not a NetBox issue. Please see the [plugins development](https://netbox.readthedocs.io/en/stable/plugins/development/) documentation for a complete list of supported components. Any component of NetBox _not_ on that list is not supported for use by plugins.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#5743