netbox-community / netbox

The premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/free-netbox-cloud/
http://netboxlabs.com/oss/netbox/
Apache License 2.0
16.04k stars 2.57k forks source link

Custom Field Choices -> Create & Add Another causes IndexError #17796

Open jacobw opened 6 days ago

jacobw commented 6 days ago

Deployment Type

Self-hosted

Triage priority

N/A

NetBox Version

v4.1.4

Python Version

3.12

Steps to Reproduce

  1. In Custom Field Choice Sets choose + Add
  2. Provide name: test and add extra choice test
  3. Click Create & Add Another

Expected Behavior

Back to Add a new custom field choice set page.

Observed Behavior

The complete exception is provided below:

<class 'IndexError'>

string index out of range

Python version: 3.12.3 NetBox version: 4.1.4 Plugins: netbox_prometheus_sd: 0.6

arthanson commented 5 days ago
  File "/Users/arthurhanson/dev/work/netbox/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/arthurhanson/dev/work/netbox/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/arthurhanson/dev/work/netbox/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/arthurhanson/dev/work/netbox/netbox/netbox/views/generic/object_views.py", line 182, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/arthurhanson/dev/work/netbox/netbox/netbox/views/generic/base.py", line 26, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/arthurhanson/dev/work/netbox/netbox/utilities/views.py", line 125, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/arthurhanson/dev/work/netbox/netbox/utilities/views.py", line 39, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/arthurhanson/dev/work/netbox/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 143, in dispatch
    return handler(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/arthurhanson/dev/work/netbox/netbox/netbox/views/generic/object_views.py", line 233, in get
    form = self.form(instance=obj, initial=initial_data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/arthurhanson/dev/work/netbox/netbox/extras/forms/model_forms.py", line 185, in __init__
    choice = (choice[0].replace(':', '\\:'), choice[1].replace(':', '\\:'))
arthanson commented 4 days ago

Looked into this a bit and it was a more complicated issue then I originally thought, some notes:

One minor issue is at the line below we are appending a tuple when it should really be an array as that is what the ArrayField returns. https://github.com/netbox-community/netbox/blob/develop/netbox/extras/forms/model_forms.py#L199

The main issue however is down in prepare_cloned_fields (https://github.com/netbox-community/netbox/blob/develop/netbox/utilities/querydict.py#L44) When you edit an existing CustomFieldChoiceSet extra_choices will be an array of arrays something like: [["x", "y"], ["q", "z"]] but when you do the select and add another extra_choices is passed into prepare_cloned_fields and get returned as a string of a single array - so it looks like prepare_cloned_fields needs to handle this special case for ArrayFields, there is a current list processing code in it but I don't think it can be directly changed as I think it is needed for other types of list fields.