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
File-backed persistence: keys differing only in case ("Config" vs "config") overwrite each other on Windows and macOS #77
PersistenceProviderUtilities.GetSafeFileName (Essentials/PersistenceProviderUtilities.cs, around lines 60–92) escapes reserved characters, control characters and device names, but it keeps letter case as-is. On file systems that ignore case (the defaults on Windows NTFS and macOS APFS), "Config" and "config" therefore map to the same file. The doc comment promises that "distinct keys always produce distinct filenames", which doesn't hold there.
Affected providers:
FileSystemPersistenceProvider: the path is built around lines 228–232, and the delete-then-move save around lines 76–80.
TempPersistenceProvider, which has the same code.
DataHome and ConfigHome, which delegate to FileSystem.
Reproduction
Tested with Testably's MockFileSystem set to behave like Windows:
InMemoryPersistenceProvider keeps both keys, so the providers disagree about the same sequence of calls.
Why it matters
Values are silently overwritten and lost, and only on Windows and macOS. Linux CI, where file systems are case-sensitive, passes.
Suggested fix / acceptance criteria
Make the encoding unambiguous whatever the case:
escape each character where char.ToLowerInvariant(c) != c, for example as ^c or %XX, add the escape character to the reserved set, and decode it in GetKeyFromFileName; or
append a stable hash suffix whenever the key contains uppercase letters.
Test: on a Windows-mode MockFileSystem, "Config" and "config" keep separate values, and both appear in GetAllKeysAsync.
Note: this changes the file names of existing stored keys that contain uppercase letters. It needs a fallback read of the old name, or a release note.
Next step: make the filename encoding case-unambiguous (escape upper-case characters, or add a hash suffix). Because existing stored keys with upper-case letters will move, plan a fallback read of the old name or a release note. Add a Windows-mode MockFileSystem test.
Activity
matt-edmondson commentedon Oct 5, 2026
Triage
PersistenceProviderUtilities.GetSafeFileName, which affects the FileSystem, Temp, DataHome and ConfigHome persistence providersNext step: make the filename encoding case-unambiguous (escape upper-case characters, or add a hash suffix). Because existing stored keys with upper-case letters will move, plan a fallback read of the old name or a release note. Add a Windows-mode
MockFileSystemtest.Generated by Claude Code