You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SaveAsync on a manager that never called InitializeAsync deletes every stored profile #124
It treats every stored profile that is not in memory as deleted. On a manager that never loaded from disk, that is every stored profile. Before 9e92fb5, saving merged with what was on disk, so those profiles survived.
Reproduction
This was executed as a scratch MSTest:
Manager A: call InitializeAsync() and CreateDefaultProfile(), create profile "vim", then SaveAsync().
Manager B on the same data directory, without calling InitializeAsync(): call CreateDefaultProfile("other", "Other"), then SaveAsync().
Manager C on the same directory: call InitializeAsync().
Observed: C loads only other. The default and vim profiles, and their bindings, are permanently deleted.
Expected: Profiles the manager never loaded are not deleted. Either keep the earlier merge behaviour, or refuse to save until the manager has loaded.
Why it matters
Forgetting InitializeAsync() is an easy mistake, for example in a code path that creates a manager only to add one profile. The penalty is silent loss of every user's custom keymaps. Deleting a profile needs proof that someone meant to delete it, and "not in memory" is not that proof when memory was never populated.
Suggested fix / acceptance criteria
Pick one:
Record the ids removed through DeleteProfile and delete only those in SaveAsync. This is the most precise option and doesn't depend on initialization.
Track whether InitializeAsync has run, and prune only if it has.
Throw InvalidOperationException from SaveAsync when the manager has not been initialized.
Add a regression test for the three-manager scenario above.
commands.json has always been overwritten wholesale in this case. That can reasonably be called misuse, but profiles are user data, and this regression is new.
Priority: High. Every stored profile is silently and permanently deleted when SaveAsync runs on a manager that was never initialized. It only takes one easy mistake.
Area / suggested owner:KeybindingManager persistence (maintainer: matt-edmondson)
Notes: The best fix is to record the ids passed to DeleteProfile and prune only those. That works whether or not InitializeAsync ran. Add the three-manager regression test.
Activity
matt-edmondson commentedon Sep 26, 2026
Triage
SaveAsyncruns on a manager that was never initialized. It only takes one easy mistake.KeybindingManagerpersistence (maintainer: matt-edmondson)DeleteProfileand prune only those. That works whether or notInitializeAsyncran. Add the three-manager regression test.Generated by Claude Code