Eventrules in v4.5.2 and v4.5.3 result in server error #301

Closed
opened 2026-04-05 16:25:10 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @chris240189 on 2/20/2026

NetBox Edition

NetBox Community

NetBox Version

v4.5.3

Python Version

3.12

Steps to Reproduce

  1. Create an event rule von Interfaces triggering on Create/Update and calling an arbitrary custom script or notification.
  2. Create a cable connection from Device A Ethernet1 to Ethernet2, let call that cable "Cable ID 3374"
  3. Edit the just created "Cable ID 3374" and alter the termination from Ethernet2 to Ethernet3.
  4. Server Error Message

Expected Behavior

The cabling changing as intended without any server errors.

Observed Behavior

Here is a screenshot of said error:

Image

Despite the error, changes on the cable will result in proper new cabling as intended, with "Cable ID 3374" now connected from Device A Ethernet1 to Device A Ethernet3.

Disabling the event rule and you will not run into the error shown.

So far I was able to reproduce this behavior in:

  • my lab environment using NetBox v4.5.3 and v4.5.2.
  • the current netbox demo
    • Python version: 3.12.3
    • NetBox version: 4.5.3

Everything works as intended in v4.5.1 in my lab. So I think something related to the v4.5.2 changes seem to be the issue.

And logs from /var/log/netbox/netbox.log

`Internal Server Error: /dcim/cables/3374/edit/
Traceback (most recent call last):
  File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/fields/related_descriptors.py", line 243, in __get__
    rel_obj = self.field.get_cached_value(instance)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/fields/mixins.py", line 37, in get_cached_value
    return instance._state.fields_cache[self.cache_name]
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
KeyError: '_path'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/netbox/venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/netbox/netbox/middleware.py", line 40, in __call__
    with apply_request_processors(request):
  File "/usr/lib/python3.12/contextlib.py", line 144, in __exit__
    next(self.gen)
  File "/opt/netbox/netbox/utilities/request.py", line 109, in apply_request_processors
    with ExitStack() as stack:
  File "/usr/lib/python3.12/contextlib.py", line 610, in __exit__
    raise exc_details[1]
  File "/usr/lib/python3.12/contextlib.py", line 595, in __exit__
    if cb(*exc_details):
       ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/contextlib.py", line 144, in __exit__
    next(self.gen)
  File "/opt/netbox/netbox/netbox/context_managers.py", line 26, in event_tracking
    flush_events(events)
  File "/opt/netbox/netbox/extras/events.py", line 245, in flush_events
    func(events)
  File "/opt/netbox/netbox/extras/events.py", line 230, in process_event_queue
    process_event_rules(
  File "/opt/netbox/netbox/extras/events.py", line 132, in process_event_rules
    if not event_rule.eval_conditions(event['data']):
                                      ~~~~~^^^^^^^^
  File "/opt/netbox/netbox/extras/events.py", line 35, in __getitem__
    data = serialize_for_event(self['object'])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/netbox/extras/events.py", line 50, in serialize_for_event
    return serializer.data
           ^^^^^^^^^^^^^^^
  File "/opt/netbox/venv/lib/python3.12/site-packages/rest_framework/serializers.py", line 573, in data
    ret = super().data
          ^^^^^^^^^^^^
  File "/opt/netbox/venv/lib/python3.12/site-packages/rest_framework/serializers.py", line 251, in data
    self._data = self.to_representation(self.instance)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/venv/lib/python3.12/site-packages/rest_framework/serializers.py", line 540, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/venv/lib/python3.12/site-packages/rest_framework/fields.py", line 1870, in to_representation
    return method(value)
           ^^^^^^^^^^^^^
  File "/opt/netbox/netbox/dcim/api/serializers_/base.py", line 32, in get_connected_endpoints
    if endpoints := obj.connected_endpoints:
                    ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/functools.py", line 995, in __get__
    val = self.func(instance)
          ^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/netbox/dcim/models/device_components.py", line 1102, in connected_endpoints
    return super().connected_endpoints
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/functools.py", line 995, in __get__
    val = self.func(instance)
          ^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/netbox/dcim/models/device_components.py", line 358, in connected_endpoints
    return self._path.destinations if self._path else []
                                      ^^^^^^^^^^
  File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/fields/related_descriptors.py", line 261, in __get__
    rel_obj = self.get_object(instance)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/fields/related_descriptors.py", line 224, in get_object
    return qs.get(self.field.get_reverse_related_filter(instance))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/query.py", line 635, in get
    raise self.model.DoesNotExist(
dcim.models.cables.CablePath.DoesNotExist: CablePath matching query does not exist.`
*Originally created by @chris240189 on 2/20/2026* ### NetBox Edition NetBox Community ### NetBox Version v4.5.3 ### Python Version 3.12 ### Steps to Reproduce 1. Create an event rule von Interfaces triggering on Create/Update and calling an arbitrary custom script or notification. 2. Create a cable connection from Device A Ethernet1 to Ethernet2, let call that cable "Cable ID 3374" 3. Edit the just created "Cable ID 3374" and alter the termination from Ethernet2 to Ethernet3. 4. Server Error Message ### Expected Behavior The cabling changing as intended without any server errors. ### Observed Behavior Here is a screenshot of said error: <img width="1305" height="592" alt="Image" src="https://github.com/user-attachments/assets/0f6c48df-b689-43c9-afc8-e50b5b4f3319" /> Despite the error, changes on the cable will result in proper new cabling as intended, with "Cable ID 3374" now connected from Device A Ethernet1 to Device A Ethernet3. Disabling the event rule and you will not run into the error shown. So far I was able to reproduce this behavior in: - my lab environment using NetBox v4.5.3 and v4.5.2. - the current netbox demo - Python version: 3.12.3 - NetBox version: 4.5.3 Everything works as intended in v4.5.1 in my lab. So I think something related to the v4.5.2 changes seem to be the issue. And logs from /var/log/netbox/netbox.log ``` `Internal Server Error: /dcim/cables/3374/edit/ Traceback (most recent call last): File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/fields/related_descriptors.py", line 243, in __get__ rel_obj = self.field.get_cached_value(instance) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/fields/mixins.py", line 37, in get_cached_value return instance._state.fields_cache[self.cache_name] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^ KeyError: '_path' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/opt/netbox/venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/netbox/netbox/middleware.py", line 40, in __call__ with apply_request_processors(request): File "/usr/lib/python3.12/contextlib.py", line 144, in __exit__ next(self.gen) File "/opt/netbox/netbox/utilities/request.py", line 109, in apply_request_processors with ExitStack() as stack: File "/usr/lib/python3.12/contextlib.py", line 610, in __exit__ raise exc_details[1] File "/usr/lib/python3.12/contextlib.py", line 595, in __exit__ if cb(*exc_details): ^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/contextlib.py", line 144, in __exit__ next(self.gen) File "/opt/netbox/netbox/netbox/context_managers.py", line 26, in event_tracking flush_events(events) File "/opt/netbox/netbox/extras/events.py", line 245, in flush_events func(events) File "/opt/netbox/netbox/extras/events.py", line 230, in process_event_queue process_event_rules( File "/opt/netbox/netbox/extras/events.py", line 132, in process_event_rules if not event_rule.eval_conditions(event['data']): ~~~~~^^^^^^^^ File "/opt/netbox/netbox/extras/events.py", line 35, in __getitem__ data = serialize_for_event(self['object']) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/netbox/extras/events.py", line 50, in serialize_for_event return serializer.data ^^^^^^^^^^^^^^^ File "/opt/netbox/venv/lib/python3.12/site-packages/rest_framework/serializers.py", line 573, in data ret = super().data ^^^^^^^^^^^^ File "/opt/netbox/venv/lib/python3.12/site-packages/rest_framework/serializers.py", line 251, in data self._data = self.to_representation(self.instance) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/venv/lib/python3.12/site-packages/rest_framework/serializers.py", line 540, in to_representation ret[field.field_name] = field.to_representation(attribute) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/venv/lib/python3.12/site-packages/rest_framework/fields.py", line 1870, in to_representation return method(value) ^^^^^^^^^^^^^ File "/opt/netbox/netbox/dcim/api/serializers_/base.py", line 32, in get_connected_endpoints if endpoints := obj.connected_endpoints: ^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/functools.py", line 995, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/netbox/dcim/models/device_components.py", line 1102, in connected_endpoints return super().connected_endpoints ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/functools.py", line 995, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/netbox/dcim/models/device_components.py", line 358, in connected_endpoints return self._path.destinations if self._path else [] ^^^^^^^^^^ File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/fields/related_descriptors.py", line 261, in __get__ rel_obj = self.get_object(instance) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/fields/related_descriptors.py", line 224, in get_object return qs.get(self.field.get_reverse_related_filter(instance)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/venv/lib/python3.12/site-packages/django/db/models/query.py", line 635, in get raise self.model.DoesNotExist( dcim.models.cables.CablePath.DoesNotExist: CablePath matching query does not exist.` ```
MrUnknownDE added the type: bugnetboxtype: bugtype: bugstatus: acceptedtype: bugseverity: lowtype: 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: bugnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxstatus: 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: acceptedseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: low labels 2026-04-05 16:25:14 +02:00
Sign in to join this conversation.
No Label netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low 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
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#301