Title: Unhandled ArgumentException after auto-save when another plugin closes/reopens the database (KeePassRPC 2.0.2)
Summary
When Kee adds or updates an entry and KeePassRPC auto-saves the database, KeePass occasionally shows an unhandled exception dialog:
System.ArgumentException: Value does not fall within the expected range.
at KeePass.UI.DocumentManagerEx.set_ActiveDocument(PwDocument value)
The save itself completes; clicking Continue lets KeePass carry on.
Environment
- KeePass 2.61.1 (installed, 64-bit), Windows 11, .NET Framework 4.8.1
- KeePassRPC 2.0.2
- KeePassMasterSlaveSync 0.99 also installed
- Browser / Kee extension version: [fill in]
Steps to reproduce
- Install KeePassRPC 2.0.2 and KeePassMasterSlaveSync 0.99.
- Open a database that has an
MSSyncJobsgroup with at least one enabled sync job. Leave KeePassRPC’s auto-save setting on (the default). - In the browser, let Kee save a new login or update an existing one.
- KeePass shows the exception dialog above.
Cause (from reading the source, not from a debugger)
saveDB in KeePassRPC/KeePassRPCService.cs stores the active PwDocument, calls UIFileSave, and then assigns the stored document back to DocumentManager.ActiveDocument.
UIFileSave raises FileSaved. KeePassMasterSlaveSync handles that event and, after running its jobs, calls DocumentManager.CloseDatabase(...) followed by MainForm.OpenDatabase(...) for the affected databases, including the master. That removes the original PwDocument from the document list and creates a new one.
When saveDB then assigns the stale document, the ActiveDocument setter throws ArgumentException because the value is not in its list. saveDB is queued with MainWindow.BeginInvoke, so nothing catches it and it surfaces as the WinForms unhandled exception dialog.
This is not specific to that plugin: anything that closes the document during the save would have the same effect. I’d expect a KeePass trigger on “Saved database file” with the action “Close active database” to reproduce it too, but I have not tested that.
Proposed fix
Only restore the previous tab if it still exists:
--- a/KeePassRPC/KeePassRPCService.cs
+++ b/KeePassRPC/KeePassRPCService.cs
@@ -158,8 +158,12 @@
_host.MainWindow.UpdateUI(false, null, true, null, true, null, true);
}
- // change tab back
- _host.MainWindow.DocumentManager.ActiveDocument = currentActiveDoc;
+ // change tab back, unless that tab no longer exists. A FileSaved handler
+ // (e.g. another plugin that closes and reopens the database after a save)
+ // can replace the PwDocument while UIFileSave runs; assigning a document
+ // that is no longer in the list makes KeePass throw an ArgumentException.
+ if (_host.MainWindow.DocumentManager.Documents.Contains(currentActiveDoc))
+ _host.MainWindow.DocumentManager.ActiveDocument = currentActiveDoc;
}
private void openGroupEditorWindow(PwGroup pg, PwDatabase db)
I’m running a local build of 2.0.2 with this change. Happy to open a pull request if that’s useful.