Problem
After deleting a user (e.g., uid=max) in Univention Corporate Server (UCS), the ox-connector.log repeatedly shows synchronization errors for this specific user. Consequently, LDAP synchronization to Open-Xchange (OX) has halted completely, preventing any new directory changes from reflecting in the OX web interface.
Error Trace from /var/log/univention/listener_modules/ox-connector.log
2026-06-12 10:38:34 INFO utils._handle_output:246 Task uid=max,cn=users,dc=company,dc=com (56819d8c-9438-103b-9ea1-cff9eabf22b5; users/user; tasks:1) now has an error count of 906
2026-06-12 10:38:34 INFO utils._handle_output:246 Error while handling uid=max,cn=users,dc=company,dc=com (56819d8c-9438-103b-9ea1-cff9eabf22b5; users/user; tasks:1)
2026-06-12 10:38:34 INFO utils._handle_output:246 No such user(s) 3227 in context 10; exceptionId -592283074-2544
2026-06-12 10:38:34 INFO utils._handle_output:246 Traceback (most recent call last):
2026-06-12 10:38:34 INFO utils._handle_output:246 File "/tmp/univention-ox-connector.listener_trigger", line 172, in main
2026-06-12 10:38:34 INFO utils._handle_output:246 run(obj)
2026-06-12 10:38:34 INFO utils._handle_output:246 File "/usr/lib/python3.9/site-packages/univention/ox/provisioning/__init__.py", line 109, in run
2026-06-12 10:38:34 INFO utils._handle_output:246 delete_user(obj)
2026-06-12 10:38:34 INFO utils._handle_output:246 File "/usr/lib/python3.9/site-packages/univention/ox/provisioning/users.py", line 565, in delete_user
2026-06-12 10:38:34 INFO utils._handle_output:246 user.remove()
2026-06-12 10:38:34 INFO utils._handle_output:246 File "/usr/lib/python3.9/site-packages/univention/ox/soap/backend.py", line 271, in remove
2026-06-12 10:38:34 INFO utils._handle_output:246 self.service(self.context_id).delete(obj)
2026-06-12 10:38:34 INFO utils._handle_output:246 File "/usr/lib/python3.9/site-packages/univention/ox/soap/services.py", line 1077, in delete
2026-06-12 10:38:34 INFO utils._handle_output:246 return self._call_ox('delete', **kwargs)
...
2026-06-12 10:38:34 INFO utils._handle_output:246 zeep.exceptions.Fault: No such user(s) 3227 in context 10; exceptionId -592283074-2544
2026-06-12 10:38:34 INFO utils._handle_output:246 Waiting for 1200 seconds for retry. In case you want to retry now, restart the univention-appcenter-listener-converter@ox-connector service
Environment
- UCS Version: 5.2-x
- OX-Connector Version: 3.0.0 or higher
Root Cause
Starting with version 3.0.0, the OX-Connector stores its synchronization task queue inside a SQLite database rather than utilizing temporary JSON files. This architecture keeps track of scheduled tasks along with historical metadata of synchronized items.
By default, the application is configured to stop queue processing immediately upon encountering an error to protect data consistency:
OX_CONNECTOR_STOP_ON_ERROR: This environment variable controls error handling behavior. When set toTrue(default), the connector halts entirely on any failed task and retries indefinitely until the administrator intervenes. Consequently, subsequent synchronization updates are blocked.- Idling between runs: In case of consecutive errors, the OX Connector now sleeps longer and longer between runs. This is done to prevent log files filling up with the same error rather quickly. The delay between runs increases with every consecutive error up to 20 minutes.
Investigation
Check the Container Configuration
Verify the current environment properties of the OX-Connector container using the following App Center command:
univention-app configure ox-connector --list
OX_SOAP_SERVER: 'https://ucs5backup.deadpool.intranet' (The server where Open-Xchange is installed)
OX_IMAP_SERVER: 'imap://ucs5backup.deadpool.intranet:143' (Default IMAP server for new users (if not set explicitely there))
OX_SMTP_SERVER: 'smtp://ucs5backup.deadpool.intranet:587' (Default SMTP server for new users (if not set explicitely there))
DEFAULT_CONTEXT: 10 (Default context for users (has to exist))
OX_LANGUAGE: 'de_DE' (Default language for new users)
LOCAL_TIMEZONE: 'Europe/Berlin' (Default timezone for new users)
OX_MASTER_ADMIN: 'oxadminmaster' (OX Admin username (the OX Admin can create, modify, delete contexts; has to exist))
OX_MASTER_PASSWORD: ',qYhiTvHg71jOzB73,3H' (OX Admin password)
Falling back to initial value for OX_IMAP_LOGIN
OX_IMAP_LOGIN: None (imapLogin field that is used by OX to log in to the user's inbox. If this value is empty it is set to the user's mail address.)
Falling back to initial value for OX_FUNCTIONAL_ACCOUNT_LOGIN_TEMPLATE
OX_FUNCTIONAL_ACCOUNT_LOGIN_TEMPLATE: None (Customizes the functional account login field format using templates. You can use plain text or incorporate UDM properties, which have to be enclosed within double curly braces, such as '{{fa_entry_uuid}}{{username}}'." For more details, please refer to the <a target="_blank" href="https://docs.software-univention.de/ox-connector-app/latest/configuration.html#envvar-OX_FUNCTIONAL_ACCOUNT_LOGIN_TEMPLATE">OX-Connector manual</a>.)
Falling back to initial value for OX_USER_IDENTIFIER
OX_USER_IDENTIFIER: None (UDM user property that is used as the unique user identifier for OX. Default: "username".)
Falling back to initial value for OX_GROUP_IDENTIFIER
OX_GROUP_IDENTIFIER: None (UDM group property that is used as the unique group identifier for OX. Default: "name".)
OX_ENABLE_DEPUTY_PERMISSIONS: False (Enables the provisioning of user deputy permissions. Additional steps are needed to activate this feature. Please refer to the instructions in the <a target="_blank")
OX_CONNECTOR_LOG_LEVEL: 'INFO' (Ox-connector log level)
OX_CONNECTOR_STOP_ON_ERROR: True (If the Connector finds an error while processing a particular object (e.g., invalid data that OX rejects), it stops. If this setting is unchecked, the App continues to process other pending tasks; the problematic object is moved to a list of errors for the Administrator to monitor at another time.)
Locate the Blocking Task
OX-Connector provides a built-in command-line tool wrapping the internal SQLite layer: univention-ox-connector-task-management.
The database contains three main tables:
tasks: Each row represents one current task of the Connector, it has not yet been successfully processed. Tasks are ordered by their creation time.old: Each row represents an object in the state it was synchronized successfully. Used when processing a task that references this object.morgue: Each row represents a task that failed to be synchronized with a certain error. These failed tasks will not be processed, they need to be individually examined by an administrator.
usage: db.py [-h] action ...
This program lets you manage the database of the OX Connector.
There are three tables:
tasks: Each row represents one current task of the Connector, it has not yet been successfully processed. Tasks are ordered by their creation time.
old: Each row represents an object in the state it was synchronized successfully. Used when processing a task that references this object.
morgue: Each row represents a task that failed to be synchronized with a certain error. These failed tasks will not be processed, they need to be individually examined by an administrator.
optional arguments:
-h, --help show this help message and exit
subcommands:
type db.py <action> --help for further help and possible arguments
action
show-item
Shows all rows in our tables that we got for an item. Other commands can
give a more verbose output:
* Last time it was synced successfully (see search-old)
* Pending tasks that shall be processed (see search-tasks)
* Current failures that may need interaction (see search-morgue)
Output can be either "simple" or "json"
resync-item
An item is resynced using the latest data that is currently saved in UDM
summarize-tasks
Shows a brief summary of the tasks table (queue of current tasks).
Output can be either "simple" or "json"
summarize-morgue
Shows a brief summary of the morgue table.
Output can be either "simple", "fuller" or "json"
add-task
Adds the content of a JSON file as a new item to the tasks table.
Note: PATH needs to be accessible from inside the OX Connector container,
e.g., in /var/lib/univention-appcenter/apps/ox-connector/data/
search-tasks
Search items from the tasks database (queue of current tasks). Items found
can be printed in different formats ("simple" or "fuller" or "json")
move-task-to-old
Move the task to the old table, meaning that this data is now
considered the last snapshot for further updates of this object. Removed
from the list of the tasks table.
move-task-to-morgue
Move the task to the morgue table, meaning that it needs further, manual
investigation. This can be used to unblock the connector. Removed from the
tasks table.
<skip>
To find the blocking task ID, extract it from the log message or run the queue status command:
univention-ox-connector-task-management search-tasks
From the log snippet, the problematic entry is identified via:
Task uid=max,cn=users,dc=company,dc=com (56819d8c-9438-103b-9ea1-cff9eabf22b5; users/user; tasks:1) now has an error count of 906 → Task ID: 1
Solution
Step 1: Unblock the Sync Queue Manually
Move the failing item out of the active tasks queue and into the morgue table to allow subsequent pending changes to process.
univention-ox-connector-task-management move-task-to-morgue --task-id=1 --error-msg="Failure of Task 1 - has an error count of 906"
After the move from the Task, the queue should be processed again, thus ensuring synchronization. Otherwise, a restart of the listener service from the ox-connector could help:
systemctl restart univention-appcenter-listener-converter@ox-connector.service
Step 2: Configure Automatic Failover (Preventative Measure)
To prevent future synchronization lockups caused by singular invalid records or unresolvable deletion states, flip the default error behavior to False.
If you now manually set the configuration to the value “False”, the ox-connector will try to process the task 5 times on a next problem, and if that is not executed successfully, the task will be moved to morgue by the ox-connector. This prevents the queue from being blocked.
You can use the following command to change the configuration, and the connector will then be restarted:
univention-app configure ox-connector --set OX_CONNECTOR_STOP_ON_ERROR=False
Advanced Management: Cleaning Up the Morgue via SQLite
The sqlite way to remove a task from the morgue table.
- Install the SQLite CLI tool if not already present:
apt install sqlite3
- Access the connector’s internal database:
sqlite3 /var/lib/univention-appcenter/apps/ox-connector/data/listener/ox-connector.db
- Inspect and query the database content:
sqlite> .tables
morgue old relations tasks
sqlite> SELECT * FROM morgue;
1|f2a4d314-2d17-4e27-bc4d-be5962c56c98|oxmail/shared_account|cn=fupo4,dc=ucs,dc=test|{"mailPrimaryAddress": "fupo4@as8-oxc-test.demo.open-xchange.com", "name": "fupo4", "univentionObjectIdentifier": "f2a4d314-2d17-4e27-bc4d-be5962c56c98", "users": []}|No|2026-04-21 11:34:47.353551
2|2d43f385-3a15-42d2-8b8c-c1eddfaa753a|oxmail/shared_account|cn=fupo5,dc=ucs,dc=test|{"contextid": "333", "mailPrimaryAddress": "fupo5@as8-oxc-test.demo.open-xchange.com", "name": "fupo5", "univentionObjectIdentifier": "2d43f385-3a15-42d2-8b8c-c1eddfaa753a"}|No|2026-04-21 12:33:11.958356
<skip>
- Delete the invalid record using its unique object identifier (
obj_id):
sqlite> DELETE FROM morgue WHERE obj_id = 'f2a4d314-2d17-4e27-bc4d-be5962c56c98';
- Cross-check your changes:
sqlite> SELECT * FROM morgue;
4|5248470d-7900-49bb-b3a6-da4b79d1e849|oxmail/shared_account|cn=fupo8,dc=ucs,dc=test|{"mailPrimaryAddress": "fupo8@as8-oxc-test.demo.open-xchange.com", "name": "fupo8", "oxContext": "333", "univentionObjectIdentifier": "5248470d-7900-49bb-b3a6-da4b79d1e849"}|No|2026-04-21 14:26:02.305375
5|5248470d-7900-49bb-b3a6-da4b79d1e849|oxmail/shared_account|cn=fupo8,dc=ucs,dc=test|{"mailPrimaryAddress": "fupo8@as8-oxc-test.demo.open-xchange.com", "name": "fupo8", "oxContext": "333", "univentionObjectIdentifier": "5248470d-7900-49bb-b3a6-da4b79d1e849", "users": [["9dfb0203-5f71-4083-a0d4-e209db1ad3af", "370c3e56-e181-478d-8b04-179a91912541"]]}|No|2026-04-21 14:26:23.427178