Workspace-scoped group management 500

The UI for managing workspace scoped groups is broken:

The link in /-/user/$username/groups/ takes you to /Owners which then 500s:

2026-01-19 13:48:48,651 [log/2547577/140659885684416] ERROR: Internal Server Error: /debian/-/groups/Owners/
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/asgiref/sync.py", line 518, in thread_handler
    raise exc_info[1]
  File "/usr/lib/python3/dist-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/asgiref/sync.py", line 518, in thread_handler
    raise exc_info[1]
  File "/usr/lib/python3/dist-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
               ^^^^^^^^^^^^^^^^^^^^^^^
        request, *callback_args, **callback_kwargs
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/lib/python3/dist-packages/asgiref/sync.py", line 468, in __call__
    ret = await asyncio.shield(exec_coro)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/asgiref/current_thread_executor.py", line 40, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/lib/python3/dist-packages/asgiref/sync.py", line 522, in thread_handler
    return func(*args, **kwargs)
  File "/usr/lib/python3.13/contextlib.py", line 85, in inner
    return func(*args, **kwds)
  File "/usr/lib/python3/dist-packages/django/views/generic/base.py", line 105, in view
    return self.dispatch(request, *args, **kwargs)
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/debusine/web/views/base.py", line 136, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/django/views/generic/base.py", line 144, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/django/views/generic/detail.py", line 108, in get
    self.object = self.get_object()
                  ~~~~~~~~~~~~~~~^^
  File "/usr/lib/python3/dist-packages/debusine/web/views/auth.py", line 399, in get_object
    group = get_object_or_404(
        cast(GroupQuerySet[Any], queryset).can_display(
    ...<3 lines>...
        name=self.kwargs["group"],
    )
  File "/usr/lib/python3/dist-packages/django/shortcuts.py", line 85, in get_object_or_404
    return queryset.get(*args, **kwargs)
           ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 640, in get
    raise self.model.MultipleObjectsReturned(
    ...<5 lines>...
    )
debusine.db.models.auth.Group.MultipleObjectsReturned: get() returned more than one Group -- it returned 6!

TODO:

  • Duplicate group web UI URLs also inside the workspace namespace (!2628 (merged))
  • Use the UI system to generate URLs to the various group UI pages, picking the right one depending on the presence of a workspace (!2628 (merged))
  • Display the workspace name, if presence, in debusine-admin group list output (!2639 (merged))
  • Update the group management commands to deal with an optional workspace name (!2639 (merged))
Edited by Enrico Zini