Skip to content

Event types registered by plugins are missing from the event rule forms #23652

Open

Description

@antoinekh

NetBox Edition

NetBox Community

NetBox Version

v4.7.4

Python Version

3.14

Steps to Reproduce

  1. Create a minimal plugin which registers an event type in ready(). docs/plugins/development/event-types.md says this "can be done anywhere within the plugin":
# probe_plugin/__init__.py
from netbox.plugins import PluginConfig


class ProbeConfig(PluginConfig):
    name = 'probe_plugin'
    verbose_name = 'Probe'
    version = '0.0.1'

    def ready(self):
        super().ready()
        from netbox.events import EventType
        EventType('probe_event', 'Probe event').register()


config = ProbeConfig
  1. Enable it with PLUGINS = ['probe_plugin'] and start NetBox.
  2. Go to Operations > Integrations > Event Rules, click Add, and open the Event types list.
  3. Go to Operations > Integrations > Event Rules, click Import, and import this CSV:
name,object_types,event_types,action_type,action_object
probe,dcim.site,probe_event,webhook,<an existing webhook name>

Expected Behavior

"Probe event" is listed in the Event types field of the add/edit form and of the bulk edit form, and the CSV import accepts probe_event, as on NetBox v4.6.

Observed Behavior

"Probe event" is not listed, and the CSV import fails with:

Select a valid choice. probe_event is not one of the available choices.

The type is registered (registry['event_types'] contains it), and the REST API accepts it, because the model field resolves its choices on each call. The same happens with the event types of netbox-branching (branch_provisioned, branch_deprovisioned, branch_synced, branch_merged, branch_reverted), so a UI user cannot create an event rule on any plugin event type.

Version Plugin event type in the event rule form
v4.6.9, v4.6.10 Yes
v4.7.0, v4.7.1, v4.7.4, main (f810ba8) No

Suspected Cause

EventRuleForm, EventRuleBulkEditForm and EventRuleImportForm call get_event_type_choices() in the class body, so the list of choices is fixed when extras.forms is first imported.

Since v4.7.0, extras.forms is imported by the extras app's own ready(), which runs before the ready() of any plugin:

extras/apps.py ready()
  -> extras/signals.py   from .cache import ...
  -> extras/cache.py     from extras.jobs import RenderConfigContextJob
  -> extras/jobs.py      from extras.scripts import _UNSET
  -> extras/scripts.py   from .forms import ScriptForm
  -> extras/forms/__init__.py -> model_forms.py, bulk_edit.py, bulk_import.py

No single commit is at fault. Two links were added on different branches, and each branch alone is correct:

The forms only worked before because nothing imported them before the plugins were ready.

Proposed Fix

Resolve the choices when the form is instantiated, which is how EventRuleFilterForm.event_type and the action_type field of EventRuleForm already work:

  • EventRuleForm and EventRuleBulkEditForm: pass choices=get_event_type_choices (the callable) instead of choices=get_event_type_choices(). Django evaluates a callable each time the choices are read.
  • EventRuleImportForm: CSVChoicesMixin passes its choices to unpack_grouped_choices() at init, which cannot iterate a callable, so set the choices in __init__() instead. The import page builds a form instance to list the accepted values, so the choices table is correct too.
diff --git a/netbox/extras/forms/bulk_edit.py b/netbox/extras/forms/bulk_edit.py
index a376e794a1..5bed256f5b 100644
--- a/netbox/extras/forms/bulk_edit.py
+++ b/netbox/extras/forms/bulk_edit.py
@@ -302,7 +302,7 @@ class EventRuleBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm):
         widget=BulkEditNullBooleanSelect()
     )
     event_types = forms.MultipleChoiceField(
-        choices=get_event_type_choices(),
+        choices=get_event_type_choices,
         required=False,
         label=_('Event types')
     )
diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py
index 06ded421ab..790566a670 100644
--- a/netbox/extras/forms/bulk_import.py
+++ b/netbox/extras/forms/bulk_import.py
@@ -317,7 +317,6 @@ class EventRuleImportForm(OwnerCSVMixin, NetBoxModelImportForm):
         help_text=_("One or more assigned object types")
     )
     event_types = CSVMultipleChoiceField(
-        choices=get_event_type_choices(),
         label=_('Event types'),
         help_text=_('The event type(s) which will trigger this rule')
     )
@@ -337,6 +336,11 @@ class EventRuleImportForm(OwnerCSVMixin, NetBoxModelImportForm):
             'owner', 'comments', 'tags'
         )
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        # Resolved per instance because plugins register event types after this module is imported
+        self.fields['event_types'].choices = get_event_type_choices()
+
     def clean(self):
         super().clean()
 
diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py
index 8f02f88e1b..385e6a63dd 100644
--- a/netbox/extras/forms/model_forms.py
+++ b/netbox/extras/forms/model_forms.py
@@ -607,7 +607,7 @@ class EventRuleForm(OwnerMixin, NetBoxModelForm):
         queryset=ObjectType.objects.with_feature('event_rules'),
     )
     event_types = MultipleChoiceField(
-        choices=get_event_type_choices(),
+        choices=get_event_type_choices,
         label=_('Event types')
     )
     action_choice = ChoiceField(

Tested on main (f810ba8) with the probe plugin above: the three forms list probe_event, the CSV import of the rule above is valid, the import field still rejects an unknown value, and an event type registered after the forms are imported is listed by the three forms. On v4.7.4 without the patch, none of these forms list probe_event and the CSV import fails with the error above.

A regression test can register an event type after the forms are imported and check that the three forms list it, removing it from registry['event_types'] in cleanup.

Volunteer

  • I volunteer to submit a fix for this bug if it is accepted

Activity

  1. added
    type: bugA confirmed report of unexpected behavior in the application
    status: needs triageThis issue is awaiting triage by a maintainer
    on Nov 10, 2026
  2. added theissue type on Nov 10, 2026
  3. added
    status: needs ownerThis issue is tentatively accepted pending a volunteer committed to its implementation
    severity: lowDoes not significantly disrupt application functionality, or a workaround is available
    severity: mediumResults in substantial degraded or broken functionality for specfic workflows
    and removed
    status: needs triageThis issue is awaiting triage by a maintainer
    on Nov 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    netboxseverity: lowDoes not significantly disrupt application functionality, or a workaround is availableseverity: mediumResults in substantial degraded or broken functionality for specfic workflowsstatus: needs ownerThis issue is tentatively accepted pending a volunteer committed to its implementationtype: bugA confirmed report of unexpected behavior in the application

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions