Python "global flags not at the start of the expression" on Device edit #11865

Closed
opened 2025-12-29 21:50:55 +01:00 by adam · 11 comments
Owner

Originally created by @stavr666 on GitHub (Nov 21, 2025).

NetBox Edition

NetBox Community

NetBox Version

v4.4.6

Python Version

3.11

Steps to Reproduce

  1. Edit any existing device.
  2. Change status.

Expected Behavior

Status changed.

Observed Behavior

All plugins disabled.
Image

Image
Originally created by @stavr666 on GitHub (Nov 21, 2025). ### NetBox Edition NetBox Community ### NetBox Version v4.4.6 ### Python Version 3.11 ### Steps to Reproduce 1. Edit any existing device. 2. Change status. ### Expected Behavior Status changed. ### Observed Behavior All plugins disabled. <img width="572" height="372" alt="Image" src="https://github.com/user-attachments/assets/7d51b367-72e4-4f32-8e56-aad822c1ab33" /> <img width="959" height="273" alt="Image" src="https://github.com/user-attachments/assets/7900bb68-5f7d-42c1-9aaa-316b0f76c2b1" />
adam added the type: bugnetbox labels 2025-12-29 21:50:55 +01:00
adam closed this issue 2025-12-29 21:50:56 +01:00
Author
Owner

@jnovinger commented on GitHub (Nov 21, 2025):

Thanks for the report, @stavr666. Unfortunately, I'm not able to reproduce this in v4.4.6.

Your STR do not really help narrow down the range of possibilities. Can you provide any more details that can help us isolate the root cause of this issue? Does it happen on every device you try to edit? Does it only happen with certain statuses? Any particular attribute of the device being edited that are different from other devices?

These STR need to include the creation of any involved objects, any configuration changes, and complete accounting of the actions being taken.

@jnovinger commented on GitHub (Nov 21, 2025): Thanks for the report, @stavr666. Unfortunately, I'm not able to reproduce this in v4.4.6. Your STR do not really help narrow down the range of possibilities. Can you provide any more details that can help us isolate the root cause of this issue? Does it happen on every device you try to edit? Does it only happen with certain statuses? Any particular attribute of the device being edited that are different from other devices? These STR need to include the creation of any involved objects, any configuration changes, and complete accounting of the actions being taken.
Author
Owner

@stavr666 commented on GitHub (Nov 21, 2025):

@jnovinger
Those objects exists in out instance since early 3.0 releases. Never experienced any issues with dozens upgrades.
Encountered this error today, after upgrading 4.4.6. Can not change any device state now. Either will find solution fast, or will roll-back update back to 4.3.4 some time later.

Can provide any necessary diagnostic, if you can tell me how to collect it. Error codes pretty useless there.

P.S. During update process, Postges autoupdated (apt upgrade) from 17.x to 18.1. Can also be cause, but need a way to collect root cause (without deployment of new Netbox instance, if possible).

@stavr666 commented on GitHub (Nov 21, 2025): @jnovinger Those objects exists in out instance since early 3.0 releases. Never experienced any issues with dozens upgrades. Encountered this error today, after upgrading 4.4.6. Can not change any device state now. Either will find solution fast, or will roll-back update back to 4.3.4 some time later. Can provide any necessary diagnostic, if you can tell me how to collect it. Error codes pretty useless there. P.S. During update process, Postges autoupdated (apt upgrade) from 17.x to 18.1. Can also be cause, but need a way to collect root cause (without deployment of new Netbox instance, if possible).
Author
Owner

@jnovinger commented on GitHub (Nov 21, 2025):

Those objects exists in out instance since early 3.0 releases. Never experienced any issues with dozens upgrades. Encountered this error today, after upgrading 4.4.6. Can not change any device state now.

Understood, thanks.

Can provide any necessary diagnostic, if you can tell me how to collect it. Error codes pretty useless there.

Ideally, the most useful thing would be a stacktrace showing where the re.error originates from (you might be able to get this if you have Sentry integration configured). Short of that, some sort of representation of a device (even if it needs to be redacted some) would be useful information.

I'm also curious if you saw any unexpected output during the upgrade process. That might have some clues. Also, was this a direct upgrade from v4.3.4 to v4.4.6?

@jnovinger commented on GitHub (Nov 21, 2025): > Those objects exists in out instance since early 3.0 releases. Never experienced any issues with dozens upgrades. Encountered this error today, after upgrading 4.4.6. Can not change any device state now. Understood, thanks. > Can provide any necessary diagnostic, if you can tell me how to collect it. Error codes pretty useless there. Ideally, the most useful thing would be a stacktrace showing where the `re.error` originates from (you might be able to get this if you have Sentry integration configured). Short of that, some sort of representation of a device (even if it needs to be redacted some) would be useful information. I'm also curious if you saw any unexpected output during the upgrade process. That might have some clues. Also, was this a direct upgrade from v4.3.4 to v4.4.6?
Author
Owner

@jnovinger commented on GitHub (Nov 21, 2025):

Also, does your installation employ any custom validators that use the re (regex) module from the Python standard library?

@jnovinger commented on GitHub (Nov 21, 2025): Also, does your installation employ any custom validators that use the `re` (regex) module from the Python standard library?
Author
Owner

@stavr666 commented on GitHub (Nov 21, 2025):

does your installation employee any custom validators that employee the re (regex) module

CUSTOM_VALIDATORS section in our configuration.py not exists. We use regex in Custom Fields validators, only 2 of them seems relevant:

Image
@stavr666 commented on GitHub (Nov 21, 2025): > does your installation employee any custom validators that employee the `re` (regex) module CUSTOM_VALIDATORS section in our configuration.py not exists. We use regex in Custom Fields validators, only 2 of them seems relevant: <img width="528" height="840" alt="Image" src="https://github.com/user-attachments/assets/24cd1892-11f5-4009-b668-1d6b814df991" />
Author
Owner

@stavr666 commented on GitHub (Nov 21, 2025):

I'm also curious if you saw any unexpected output during the upgrade process. That might have some clues. Also, was this a direct upgrade from v4.3.4 to v4.4.6?

No any errors or warnings encountered. Shamefully, not saved full log this time.

@stavr666 commented on GitHub (Nov 21, 2025): > I'm also curious if you saw any unexpected output during the upgrade process. That might have some clues. Also, was this a direct upgrade from v4.3.4 to v4.4.6? No any errors or warnings encountered. Shamefully, not saved full log this time.
Author
Owner

@stavr666 commented on GitHub (Nov 21, 2025):

Short of that, some sort of representation of a device (even if it needs to be redacted some) would be useful information.

Screenshot? Api representation?

@stavr666 commented on GitHub (Nov 21, 2025): > Short of that, some sort of representation of a device (even if it needs to be redacted some) would be useful information. Screenshot? Api representation?
Author
Owner

@jnovinger commented on GitHub (Nov 21, 2025):

Bingo! Apparently in Python 3.11+, you can no longer include global flags, like (?i), at the beginning of regexes any more, like your ^(?i)https?\/\//? ... regex on Device, Cluster, and FHRPGRoup.

@jnovinger commented on GitHub (Nov 21, 2025): Bingo! Apparently in Python 3.11+, you can no longer include global flags, like `(?i)`, at the beginning of regexes any more, like your `^(?i)https?\/\//? ...` regex on Device, Cluster, and FHRPGRoup.
Author
Owner

@jnovinger commented on GitHub (Nov 21, 2025):

Ah, apparently I may have gotten that wrong. The global flags can no longer be anywhere but the beginning. So, perhaps before the ^ beginning-of-line matcher?

The stack trace I was able to produce:

Traceback (most recent call last):
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/views/generic/base.py", line 105, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/development/netbox-community/netbox/netbox/netbox/views/generic/object_views.py", line 190, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/development/netbox-community/netbox/netbox/netbox/views/generic/base.py", line 26, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/development/netbox-community/netbox/netbox/utilities/views.py", line 144, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/development/netbox-community/netbox/netbox/utilities/views.py", line 45, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/views/generic/base.py", line 144, in dispatch
    return handler(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/development/netbox-community/netbox/netbox/netbox/views/generic/object_views.py", line 288, in post
    if form.is_valid():
       ^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/forms.py", line 206, in is_valid
    return self.is_bound and not self.errors
                                 ^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/forms.py", line 201, in errors
    self.full_clean()
    ^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/forms.py", line 337, in full_clean
    self._clean_fields()
    ^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/forms.py", line 345, in _clean_fields
    self.cleaned_data[name] = field._clean_bound_field(bf)
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/fields.py", line 273, in _clean_bound_field
    return self.clean(value)
           ^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/fields.py", line 210, in clean
    self.run_validators(value)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/fields.py", line 195, in run_validators
    v(value)
    ^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/core/validators.py", line 52, in __call__
    regex_matches = self.regex.search(str(value))
                    ^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/utils/functional.py", line 251, in inner
    self._setup()
    ^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/utils/functional.py", line 404, in _setup
    self._wrapped = self._setupfunc()
                    ^^^^^^^^^^^^^^^^^
  File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/utils/regex_helper.py", line 349, in _compile
    return re.compile(regex, flags)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/__init__.py", line 289, in compile
    return _compile(pattern, flags)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/__init__.py", line 350, in _compile
    p = _compiler.compile(pattern, flags)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/_compiler.py", line 748, in compile
    p = _parser.parse(p, flags)
        ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/_parser.py", line 980, in parse
    p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/_parser.py", line 459, in _parse_sub
    itemsappend(_parse(source, state, verbose, nested + 1,
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/_parser.py", line 841, in _parse
    raise source.error('global flags not at the start '
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Exception Type: PatternError at /tenancy/tenants/7/edit/
Exception Value: global flags not at the start of the expression at position 1
@jnovinger commented on GitHub (Nov 21, 2025): Ah, apparently I may have gotten that wrong. The global flags [can no longer be anywhere _but_ the beginning](https://bugs.python.org/issue47066). So, perhaps before the `^` beginning-of-line matcher? The stack trace I was able to produce: ``` Traceback (most recent call last): File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/core/handlers/base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/views/generic/base.py", line 105, in view return self.dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/development/netbox-community/netbox/netbox/netbox/views/generic/object_views.py", line 190, in dispatch return super().dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/development/netbox-community/netbox/netbox/netbox/views/generic/base.py", line 26, in dispatch return super().dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/development/netbox-community/netbox/netbox/utilities/views.py", line 144, in dispatch return super().dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/development/netbox-community/netbox/netbox/utilities/views.py", line 45, in dispatch return super().dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/views/generic/base.py", line 144, in dispatch return handler(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/development/netbox-community/netbox/netbox/netbox/views/generic/object_views.py", line 288, in post if form.is_valid(): ^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/forms.py", line 206, in is_valid return self.is_bound and not self.errors ^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/forms.py", line 201, in errors self.full_clean() ^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/forms.py", line 337, in full_clean self._clean_fields() ^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/forms.py", line 345, in _clean_fields self.cleaned_data[name] = field._clean_bound_field(bf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/fields.py", line 273, in _clean_bound_field return self.clean(value) ^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/fields.py", line 210, in clean self.run_validators(value) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/forms/fields.py", line 195, in run_validators v(value) ^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/core/validators.py", line 52, in __call__ regex_matches = self.regex.search(str(value)) ^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/utils/functional.py", line 251, in inner self._setup() ^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/utils/functional.py", line 404, in _setup self._wrapped = self._setupfunc() ^^^^^^^^^^^^^^^^^ File "/Users/jnovinger/.virtualenvs/netbox/lib/python3.13/site-packages/django/utils/regex_helper.py", line 349, in _compile return re.compile(regex, flags) ^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/__init__.py", line 289, in compile return _compile(pattern, flags) ^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/__init__.py", line 350, in _compile p = _compiler.compile(pattern, flags) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/_compiler.py", line 748, in compile p = _parser.parse(p, flags) ^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/_parser.py", line 980, in parse p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/_parser.py", line 459, in _parse_sub itemsappend(_parse(source, state, verbose, nested + 1, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/re/_parser.py", line 841, in _parse raise source.error('global flags not at the start ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Exception Type: PatternError at /tenancy/tenants/7/edit/ Exception Value: global flags not at the start of the expression at position 1 ```
Author
Owner

@stavr666 commented on GitHub (Nov 21, 2025):

Thanks for help. We'll fix it then 🤦🏿

@stavr666 commented on GitHub (Nov 21, 2025): Thanks for help. We'll fix it then 🤦🏿
Author
Owner

@jnovinger commented on GitHub (Nov 21, 2025):

Closing this as expected behavior, for Python 3.11+ installations.

@jnovinger commented on GitHub (Nov 21, 2025): Closing this as expected behavior, for Python 3.11+ installations.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#11865