Sync stuck at "Waiting for other operations to finish"

edited today at 5:26am
ItemTree._resetColumns() never settles when a plugin registers a column at startup

**Environment:** Zotero 10.0.6 (build 20261007113827), macOS, Apple Silicon

**Symptom**
After startup, the sync status stays at "Waiting for other operations to finish" indefinitely. Other plugins' startup registrations fail with `TimeoutError` from db.js.

**Minimal reproduction**
1. Disable all plugins except one that calls `Zotero.ItemTreeManager.registerColumn()` in `onStartup`. I used zotero-AI-Butler 4.1.0-beta.2, but I've seen the same with Citation Tally, Attachment Scanner and Better Authors.
2. Restart Zotero with auto-sync enabled.
3. Sync never starts. The debug output shows:

```
registerColumn@chrome://zotero/content/xpcom/pluginAPI/itemTreeManager.js:277:34
registerLibraryStatusColumn@zotero-ai-butler@github.com.xpi!/content/scripts/aiButler.js:91325:47
onStartup@zotero-ai-butler@github.com.xpi!/content/scripts/aiButler.js:92003:5
(4)(+0000000): Beginning DB transaction HbmIhIJ4
(3)(+0000001): Transaction in progress -- waiting to sync
(4)(+0000000): Waiting for DB transaction HbmIhIJ4 to finish to start sync
Zotero.Sync.Runner_Module/this._sync@chrome://zotero/content/xpcom/sync/syncRunner.js:180:25
(4)(+0000000): Committed DB transaction HbmIhIJ4
(3)(+0000000): Committing notifier event queue [refresh-itemtree: 0]
(3)(+0000000): Notifier.trigger('refresh', 'itemtree', [], {}) called [observers: 2]
JavaScript error: chrome://zotero/content/itemTree.js, line 2941: TypeError: can't access property "_resetColumns", this.tree is undefined
(1)(+0000265): Timed out waiting for transaction TsbzCCU2
(1)(+0000002): Timed out waiting for transaction taeIfW7E
```
After 60+ seconds, sync is still waiting, and there is no "Done syncing".

**Analysis**
- `registerColumn()` runs a transaction. On commit it fires `refresh`/`itemtree`, and `ItemTree.notify()` awaits `this._resetColumns()`.
- `_resetColumns()` (itemTree.jsx, unchanged on `main` as of today) only resolves its promise inside the `forceUpdate` callback, after `await this.tree._resetColumns()`. For an item tree that hasn't rendered yet, `this.tree` is undefined. The callback throws, so the promise **never settles**.
- `executeTransaction()` awaits the commit callbacks before resolving `_transactionPromise` in `finally`. So that promise never resolves either.
- Anything that called `waitForTransaction()` while that transaction was open hangs. `executeTransaction()` waiters give up after the 30 s `waitTimeout`, so plugin registrations fail. `Sync.Runner._sync()` (syncRunner.js ~L176–181) awaits `waitForTransaction('sync')` with no timeout, so sync hangs until restart.

**Suggested fix** (just a sketch)
```js
async _resetColumns() {
this._columnsId = null;
if (!this.tree) return; // not rendered yet; columns are read fresh on first render
return new Promise((resolve, reject) => this.forceUpdate(async () => {
try {
await this.tree._resetColumns();
resolve();
}
catch (e) {
reject(e);
}
}));
}
```
A timeout on the sync runner's `waitForTransaction('sync')` would also stop a single stuck commit callback from blocking sync for the whole session.

**Related reports**
- Same TypeError at itemTree.js:2941 with db.js TimeoutErrors on 10.0-beta.23: https://forums.zotero.org/discussion/comment/516577
- A plugin author traced the same mechanism ("A list whose tree has not been rendered yet has no `tree`, and Zotero does not check for that"), but could not avoid it from the plugin side, because waiting for the main window's item list didn't help: https://github.com/JanR383/zotero-qualified-references/pull/72

Sign In or Register to comment.