Skip to content

Settings app crashes when opening Command Palette page (FileSystemWatcher throws FileNotFoundException on MSIX LocalState junction) #49248

Description

@apnn633

Summary

PowerToys Settings app crashes (flashes and exits) every time the user clicks the Command Palette entry in the left navigation. The crash is a System.IO.FileNotFoundException thrown by FileSystemWatcher.StartRaisingEvents() inside CmdPalViewModel's constructor, which is not caught by any handler.

This happens when the Command Palette (an MSIX-packaged app) has its LocalState folder redirected to a non-system drive via a mount point (junction) — which is the standard behavior when Windows "Storage Sense → Change where new content is saved → New apps will save to" is set to a non-C: drive. The LocalState directory itself exists and is readable, but FileSystemWatcher fails to start watching it with ERROR_FILE_NOT_FOUND (0x80070002).

Reproduction

Environment

  • OS: Windows 11 Build 26200
  • PowerToys: 0.100.2.0 (latest via winget)
  • Command Palette MSIX: Microsoft.CommandPalette 0.11.11762.0
  • .NET Runtime: 10.0.9
  • Windows storage setting: "New apps will save to" = D: (non-system drive)
  • User profile path: contains non-ASCII characters (C:\Users\user), account SAM name is ASCII (luo)

Steps

  1. Have Windows "Change where new content is saved → New apps will save to" set to a non-C: drive (e.g. D:).
  2. Install PowerToys 0.100.2 (Command Palette module enabled).
  3. Launch Command Palette at least once (so the MSIX LocalState junction is created at C:\Users\<user>\AppData\Local\Packages\Microsoft.CommandPalette_8wekyb3d8bbwe\LocalState, pointing to D:\WpSystem\<SID>\AppData\Local\Packages\Microsoft.CommandPalette_8wekyb3d8bbwe\LocalState).
  4. Open PowerToys Settings.
  5. Click Command Palette in the left nav.
  6. Settings app freezes briefly, then crashes to desktop.

Expected

Settings navigates to the Command Palette settings page (or, at worst, shows an error and stays open).

Actual

PowerToys.Settings.exe crashes. Windows Event Viewer shows:

Faulting application name: PowerToys.Settings.exe, version: 0.100.2.0
Faulting module name: Microsoft.UI.Xaml.dll, version: 3.2.0.0
Exception code: 0xc000027b

Root cause

The settings page's ViewModel constructs a FileSystemWatcher on the Command Palette's LocalState directory without any exception handling:

Microsoft.PowerToys.Settings.UI.ViewModels.CmdPalViewModel..ctor(...)
  → Microsoft.PowerToys.Settings.UI.Library.Utilities.Helper.GetFileWatcher(path, ...)
    → System.IO.Abstractions.FileSystemWatcherWrapper.set_EnableRaisingEvents(true)
      → System.IO.FileSystemWatcher.StartRaisingEvents()  ← throws here

When the watched directory is a reparse point (mount point/junction) — which it always is for any MSIX app installed under the "new apps save to D:" storage policy — ReadDirectoryChangesW fails and EnableRaisingEvents throws FileNotFoundException (HRESULT 0x80070002). The exception is unhandled and propagates up through the XAML Frame.NavigateNavigationView invocation, terminating the process.

Full stack trace (identical across 6 crashes)

System.IO.FileNotFoundException (-2147024894): Error reading the C:\Users\user\AppData\Local\Packages\Microsoft.CommandPalette_8wekyb3d8bbwe\LocalState directory.
   at System.IO.FileSystemWatcher.StartRaisingEvents()
   at System.IO.Abstractions.FileSystemWatcherWrapper.set_EnableRaisingEvents(Boolean value)
   at Microsoft.PowerToys.Settings.UI.Library.Utilities.Helper.GetFileWatcher(String path, Action onChangedCallback, IFileSystem fileSystem)
   at Microsoft.PowerToys.Settings.UI.ViewModels.CmdPalViewModel..ctor(SettingsUtils settingsUtils, ISettingsRepository`1 settingsRepository, Func`2 ipcMSGCallBackFunc, DispatcherQueue uiDispatcherQueue)
   at Microsoft.PowerToys.Settings.UI.Views.CmdPalPage..ctor()
   at Microsoft.PowerToys.Settings.UI.PowerToys_Settings_XamlTypeInfo.XamlTypeInfoProvider.Activate_240_CmdPalPage()
   at Microsoft.PowerToys.Settings.UI.PowerToys_Settings_XamlTypeInfo.XamlUserType.ActivateInstance()
   at ABI.Microsoft.UI.Xaml.Markup.IXamlType.Do_Abi_ActivateInstance_13(IntPtr thisPtr, IntPtr* result)
--- End of stack trace from previous location ---
   at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|38_0(Int32 hr)
   at ABI.Microsoft.UI.Xaml.Controls.IFrameMethods.Navigate(IObjectReference _obj, Type sourcePageType, Object parameter, NavigationTransitionInfo infoOverride)
   at Microsoft.UI.Xaml.Controls.Frame.Navigate(...)
   at Microsoft.PowerToys.Settings.UI.Services.NavigationService.Navigate(...)
   at Microsoft.PowerToys.Settings.UI.ViewModels.ShellViewModel.OnItemInvoked(NavigationViewItemInvokedEventArgs args)

Reproduced outside PowerToys

I reproduced the exact same exception (FileNotFoundException, HRESULT 0x80070002, identical "Error reading the X directory" message) with a minimal .NET 10 console app that creates a FileSystemWatcher on a mount point whose target does not exist:

var w = new FileSystemWatcher(junctionPath);  // junction → missing target
w.EnableRaisingEvents = true;  // throws FileNotFoundException (0x80070002)

Output:

FSW on dangling junction FAILED: FileNotFoundException
  Message: Error reading the C:\Users\user\AppData\Local\Temp\fsw_junction_... directory.
  HRESULT: 0x80070002

Impact

  • Severity: High — the entire Settings app is killed, not just the page. Users lose any unsaved changes in other settings pages.
  • Scope: Affects every user who has "new apps save to D:" enabled AND uses the Command Palette. This is a common configuration for users with a small system SSD + large data HDD. 21 of 171 installed MSIX packages on my machine are redirected this way.
  • Only Command Palette page is affected — all other settings pages work because their data folders are plain local directories, not reparse points.

Suggested fix

Helper.GetFileWatcher (and/or CmdPalViewModel's constructor) should defensively handle the case where FileSystemWatcher.EnableRaisingEvents throws. For example:

try
{
    watcher.EnableRaisingEvents = true;
}
catch (FileNotFoundException)
{
    // The path is a reparse point (mount point/junction) whose target
    // is not resolvable for ReadDirectoryChangesW. Fall back to no
    // auto-refresh — the settings page should still open.
    watcher.Dispose();
    watcher = null;
}

At minimum, catching the exception in the ViewModel constructor would let the page open without live file-watch refresh, rather than killing the whole Settings process.

Workarounds (for affected users)

  1. Replace the junction with a plain local directory (works, but the OS may recreate the junction on package updates):
    • Back up settings.json / state.json from the D: target.
    • rmdir the junction (does not delete the target).
    • mkdir a plain LocalState folder on C:.
    • Restore the two json files.
  2. Avoid the Settings page — edit settings.json directly, or use the Command Palette's own in-app settings UI (invoked from the palette itself, which does not go through this code path).

PowerToysReport

A full PowerToysReport was collected; the relevant Settings\Logs\0.100.2.0\Log_2026-07-10.log contains 6 identical crash entries between 11:29 and 11:52 (all same stack trace above).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Product-Command PaletteRefers to the Command Palette utilityProduct-SettingsThe standalone PowerToys Settings application

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions