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
Found while re-testing the #870 fix (v1.19.3) on real Mac hardware. This is a separate bug from #870 — the file-move issue #870 fixed is confirmed working correctly; this is a new issue surfaced immediately after.
Setup: Same reproduction as #870 — v1.18.0 with a custom-location database (Documents) plus the untouched default database, real username/home location entered, then upgraded directly to v1.19.3.
What the log shows (full opensak.log, settings_migration debug channel):
_rewrite_stale_install_dir_paths() opens the moved file, finds it contains the real settings (2 databases, real username), and correctly rewrites 1 stale path field (databases.list[0].path).
_load_from_settings: databases.list=[], databases.active=None, databases.dir=None
WARNING: Ingen kendte databaser fundet i settings (...) — opretter en frisk, tom 'Default'-database
Checking opensak.json on disk immediately afterward shows it now contains only fresh, empty defaults — the real data (username, home location, both database entries) is gone.
Analysis:
_load_from_settings() calls _save_to_settings()unconditionally right after parsing (before the if not self._databases: fallback check):
# Gem migrerede stier tilbage (én gang)self._save_to_settings()
# Hvis ingen databaser kendes, opret Defaultifnotself._databases:
...
If self._databases ends up empty at that point — for whatever reason store.get("databases.list", []) returned [] instead of the two real entries — this call persists that empty state straight back to opensak.json, permanently overwriting the correctly-migrated data that was on disk a moment earlier. The subsequent fallback-default logic then calls _save_to_settings() a second time, compounding it.
I could not reproduce the databases.list=[] read itself in isolation — a standalone Python reproduction of the exact same migrate_macos_default_paths() → get_store() → DatabaseManager() sequence, with the same data, correctly returns the real 2-entry list from store.get("databases.list"). This suggests the discrepancy is specific to the real, compiled/signed macOS app bundle rather than the settings-store logic itself — possibly something related to running from a notarized PyInstaller .app (in the same spirit as the already-documented Windows MSIX path-virtualization issue), though this is unconfirmed.
Suggested next steps:
Make _save_to_settings() non-destructive when it has nothing meaningful to save — e.g. don't call it before the fallback-default block if self._databases is empty, since that write can only ever lose data at that specific point, never gain any. Move the initial _save_to_settings() call to after the fallback logic instead, so it's called exactly once, with the final, correct state.
Add a debug line right at the top of _load_from_settings() printing id(store) and the raw store._data dict (not just the two keys), to determine whether this is the sameSettingsStore singleton instance seeing empty data (a real read bug) versus a different instance entirely (a singleton/caching bug).
Since I couldn't reproduce this outside the real app, next reproduction attempt should ideally run from source (python run.py) on the same Mac, not the compiled .app, to help isolate whether PyInstaller packaging/signing is a factor.
Found while re-testing the #870 fix (v1.19.3) on real Mac hardware. This is a separate bug from #870 — the file-move issue #870 fixed is confirmed working correctly; this is a new issue surfaced immediately after.
Setup: Same reproduction as #870 — v1.18.0 with a custom-location database (Documents) plus the untouched default database, real username/home location entered, then upgraded directly to v1.19.3.
What the log shows (full
opensak.log,settings_migrationdebug channel):migrate_macos_default_paths()runs, finds real data in the old directory, and successfully moves and verifiesopensak.json(flyttede .../opensak.json (verificeret)) — confirming the Add a permanent, in-place backup of opensak.json before the macOS #825 migration touches it #870 fix works as intended._rewrite_stale_install_dir_paths()opens the moved file, finds it contains the real settings (2 databases, real username), and correctly rewrites 1 stale path field (databases.list[0].path).DatabaseManager._load_from_settings()logs:opensak.jsonon disk immediately afterward shows it now contains only fresh, empty defaults — the real data (username, home location, both database entries) is gone.Analysis:
_load_from_settings()calls_save_to_settings()unconditionally right after parsing (before theif not self._databases:fallback check):If
self._databasesends up empty at that point — for whatever reasonstore.get("databases.list", [])returned[]instead of the two real entries — this call persists that empty state straight back toopensak.json, permanently overwriting the correctly-migrated data that was on disk a moment earlier. The subsequent fallback-default logic then calls_save_to_settings()a second time, compounding it.I could not reproduce the
databases.list=[]read itself in isolation — a standalone Python reproduction of the exact samemigrate_macos_default_paths()→get_store()→DatabaseManager()sequence, with the same data, correctly returns the real 2-entry list fromstore.get("databases.list"). This suggests the discrepancy is specific to the real, compiled/signed macOS app bundle rather than the settings-store logic itself — possibly something related to running from a notarized PyInstaller.app(in the same spirit as the already-documented Windows MSIX path-virtualization issue), though this is unconfirmed.Suggested next steps:
_save_to_settings()non-destructive when it has nothing meaningful to save — e.g. don't call it before the fallback-default block ifself._databasesis empty, since that write can only ever lose data at that specific point, never gain any. Move the initial_save_to_settings()call to after the fallback logic instead, so it's called exactly once, with the final, correct state._load_from_settings()printingid(store)and the rawstore._datadict (not just the two keys), to determine whether this is the sameSettingsStoresingleton instance seeing empty data (a real read bug) versus a different instance entirely (a singleton/caching bug).python run.py) on the same Mac, not the compiled.app, to help isolate whether PyInstaller packaging/signing is a factor.