Problem
The OX Connector provisioning queue no longer progresses. A specific OX group repeatedly fails during processing and blocks subsequent provisioning tasks.
The connector log contains an error similar to:
Error while handling cn=<group>,cn=groups,dc=example,dc=com
'NoneType' object has no attribute 'get'
Traceback (most recent call last):
...
context = get_context_id(user_obj.attributes)
...
context_id = attributes.get("oxContext")
AttributeError: 'NoneType' object has no attribute 'get'
The affected group may accumulate a very high error count:
Task cn=<group>,cn=groups,dc=example,dc=com (...) now has an error count of ...
Other groups and users remain in the provisioning queue because the connector repeatedly retries the failing group task.
Investigation
First, identify the user object that is processed immediately before the group fails:
grep -B 20 -F \
"Error while handling cn=<group>,cn=groups,dc=example,dc=com" \
/var/log/univention/listener_modules/ox-connector.log |
grep -F "Loading old object for" |
tail -n 1
Example:
Loading old object for uid=user.name,cn=users,dc=example,dc=com
The OX Connector stores previously processed objects in its SQLite database:
/var/lib/univention-appcenter/apps/ox-connector/data/listener/ox-connector.db
Check the cached entry for the affected user:
sqlite3 -header -column \
/var/lib/univention-appcenter/apps/ox-connector/data/listener/ox-connector.db \
"SELECT id, obj_id, udm_module, dn, quote(attrs)
FROM old
WHERE dn='uid=user.name,cn=users,dc=example,dc=com';"
In the affected case, the entry contained an invalid attribute value:
attrs = 'null'
When the connector decodes this JSON value, it becomes Python None. The group provisioning code subsequently attempts to access:
attributes.get("oxContext")
This results in the NoneType exception.
The cached object identifier must also be compared with the current LDAP object:
univention-ldapsearch -LLL \
-b "uid=user.name,cn=users,dc=example,dc=com" \
-s base \
entryUUID univentionObjectIdentifier
The OX Connector database column obj_id, and the entry_uuid field used in App Center listener JSON files, refer to the LDAP attribute:
univentionObjectIdentifier
They do not necessarily refer to the LDAP operational attribute entryUUID.
In this case, the obj_id stored in the OX Connector database no longer matched the current univentionObjectIdentifier of the user object.
Root Cause
The OX Connector contained a stale or inconsistent entry for the affected user in its internal old table.
The entry had two problems:
- Its stored object identifier did not match the current
univentionObjectIdentifierof the LDAP user object. - Its cached attributes contained the JSON value
nullinstead of a valid attribute dictionary.
During group provisioning, the connector loads the cached state of each group member. It found the stale user entry by its DN, decoded the stored attributes as None, and then failed while trying to determine the user’s OX context.
The available data does not conclusively show how the stale identifier was originally created. Possible causes include:
- The LDAP user object was deleted and later recreated under the same DN.
- An old connector state survived an update or database migration.
- A previous provisioning operation stored an incomplete user state.
The connector did not handle this inconsistent cached entry defensively, allowing one affected group member to block the provisioning queue.
Solution
Stop the OX Connector listener converter and create a backup of its database:
SERVICE=univention-appcenter-listener-converter@ox-connector.service
DB=/var/lib/univention-appcenter/apps/ox-connector/data/listener/ox-connector.db
systemctl stop "$SERVICE"
cp -a "$DB" "${DB}.$(date +%F-%H%M%S).bak"
Verify the affected entry before deleting it:
USER_DN='uid=user.name,cn=users,dc=example,dc=com'
sqlite3 -header -column "$DB" "
SELECT id, obj_id, udm_module, dn, quote(attrs) AS attrs
FROM old
WHERE dn='$USER_DN';
"
Example output:
id obj_id udm_module dn attrs
--- ----------------------------------- ---------- ----------------------------------------- ------
290 6cb09cf1-1117-418d-9153-22a540a8c9fd users/user uid=user.name,cn=users,dc=example,dc=com 'null'
The value in the id column is the internal database ID of the cached entry. In this example, the database ID is 290.
Assign this value to a variable:
DATABASE_ID=290
Then delete only the previously verified entry:
sqlite3 "$DB" "
DELETE FROM old
WHERE id=$DATABASE_ID
AND udm_module='users/user'
AND dn='$USER_DN';
SELECT changes();
"
SELECT changes() must return:
1
If it returns 0, the specified entry was not found and nothing was deleted. If the initial query returns more than one entry, do not delete anything until the individual records and their object identifiers have been examined.
Restart the listener converter:
systemctl start "$SERVICE"
Determine the current univentionObjectIdentifier of the user:
USER_DN='uid=user.name,cn=users,dc=example,dc=com'
USER_OBJECT_ID="$(
univention-ldapsearch -LLL \
-b "$USER_DN" \
-s base \
univentionObjectIdentifier |
sed -n 's/^univentionObjectIdentifier: //p'
)"
printf '%s\n' "$USER_OBJECT_ID"
Create a listener JSON file to trigger the user again:
LISTENER_DIR=/var/lib/univention-appcenter/listener/ox-connector
cat >"$LISTENER_DIR/$(date +%Y-%m-%d-%H-%M-%S-%6N).json" <<EOF
{
"entry_uuid": "$USER_OBJECT_ID",
"dn": "$USER_DN",
"object_type": "users/user",
"command": "modify"
}
EOF
Although the JSON field is named entry_uuid, it must contain the current univentionObjectIdentifier in this connector setup.
Monitor the connector log:
tail -f /var/log/univention/listener_modules/ox-connector.log
After the user has been processed successfully, verify that a valid cache entry has been created:
sqlite3 -header -column "$DB" "
SELECT
id,
obj_id,
dn,
length(attrs) AS attrs_length,
substr(attrs, 1, 80) AS attrs_start
FROM old
WHERE dn='$USER_DN';
"
The obj_id must match the current univentionObjectIdentifier, and attrs_start should begin with { instead of containing null.
Finally, trigger the affected group in the same way:
GROUP_DN='cn=<group>,cn=groups,dc=example,dc=com'
GROUP_OBJECT_ID="$(
univention-ldapsearch -LLL \
-b "$GROUP_DN" \
-s base \
univentionObjectIdentifier |
sed -n 's/^univentionObjectIdentifier: //p'
)"
cat >"$LISTENER_DIR/$(date +%Y-%m-%d-%H-%M-%S-%6N).json" <<EOF
{
"entry_uuid": "$GROUP_OBJECT_ID",
"dn": "$GROUP_DN",
"object_type": "groups/group",
"command": "modify"
}
EOF
Confirm that the user and group are processed without errors:
grep -E \
'user\.name|<group>|Error while handling|NoneType' \
/var/log/univention/listener_modules/ox-connector.log |
tail -n 100
Also verify that no provisioning tasks remain:
/usr/sbin/univention-ox-connector-task-management summarize-tasks
Expected result:
Total: 0
After rebuilding the user cache entry with the correct univentionObjectIdentifier, the group can determine the user’s OX context normally and the remaining provisioning tasks are processed successfully.