Problem
When executing the verify.py script of the ucsschool-id-connector app with the workgroups subcommand, the script aborts with an AttributeError:
root@ucs:/var/lib/univention-appcenter/apps/ucsschool-id-connector/conf/plugins/packages/idbroker# ./verify.py workgroups -a bremen --fix
2026-03-10 08:19:51.519134 Searching LDAP with filter '(ucsschoolRole=workgroup:*)'...
2026-03-10 08:19:56.956869 Found 1431 objects in 5.44 seconds.
Traceback (most recent call last):
File "/var/lib/univention-appcenter/apps/ucsschool-id-connector/conf/plugins/packages/idbroker/./verify.py", line 664, in <module>
cli()
...
File "/var/lib/univention-appcenter/apps/ucsschool-id-connector/conf/plugins/packages/idbroker/./verify.py", line 376, in ldap_object_to_workgroup
school = WORKGROUP_DN_PATTERN.match(ldap_object.entry_dn).groupdict()["ou"]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'groupdict'
Root Cause
The verify.py script expects all work groups to reside inside the standard UCS@school container structure, for example:
cn=<workgroup-name>,cn=schueler,cn=groups,ou=<SCHOOL>,<base-dn>
For each work group object found in LDAP, the script extracts the school OU from the DN by applying a regular expression (WORKGROUP_DN_PATTERN):
school = WORKGROUP_DN_PATTERN.match(ldap_object.entry_dn).groupdict()["ou"]
If a work group is located outside the expected container hierarchy, the regular expression does not match. In that case WORKGROUP_DN_PATTERN.match(...) returns None, and calling .groupdict() on None raises the AttributeError shown above.
In short: at least one work group object in the LDAP directory has a DN that does not conform to the UCS@school DN pattern expected by verify.py.
Investigation
To identify the offending work group, list all DNs of objects marked as work groups in LDAP:
univention-ldapsearch -LLL "(ucsschoolRole=workgroup:school:*)" dn
Compare the returned DNs against the expected pattern. A valid DN looks like this:
dn: cn=Heisenberg-Test-Workgroup,cn=schueler,cn=groups,ou=Heisenberg,dc=example,dc=intranet
An invalid DN, one that triggers the error, is located outside the school OU structure, for example directly under the base DN:
dn: cn=Heisenberg-Test-Workgroup,cn=groups,dc=example,dc=intranet
Solution
Move the misplaced work group object into the correct UCS@school container structure.
-
Identify the work group(s) with an invalid DN using the LDAP search above.
-
Open the UMC module LDAP directory.
-
Navigate to the misplaced work group object.
-
Move the object to the correct container, for example:
ou=<SCHOOL>/cn=groups/cn=schueler/ -
Verify that the DN now matches the expected pattern:
univention-ldapsearch -LLL "(ucsschoolRole=workgroup:school:*)" dnExample after correction:
dn: cn=Heisenberg-Test-Workgroup,cn=schueler,cn=groups,ou=Heisenberg,dc=example,dc=intranet -
Re-run the verification:
./verify.py workgroups -a <authority> --fix
The script should now process all work groups without raising the AttributeError.
Additional Notes
- Work group objects must always be created and managed via the UCS@school tools (UMC modules,
ucsschoolCLI, or the import framework) to ensure they end up in the correct container. - Manually created group objects with
ucsschoolRole=workgroup:school:*outside the UCS@school structure are not supported and will break consistency checks such asverify.py.