{"record":{"id":"113e980b93afbe3c","repo":"lepoco/wpfui","slug":"could-not-get-window-handle","errorCode":null,"errorMessage":"Could not get window handle.","messagePattern":"Could not get window handle\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Wpf.Ui/Appearance/SystemThemeWatcher.cs","lineNumber":72,"sourceCode":"        {\n            ObserveWindowWhenLoaded(window, backdrop, updateAccents);\n        }\n\n        if (_observedWindows.Count == 0)\n        {\n            System.Diagnostics.Debug.WriteLine(\n                $\"INFO | {typeof(SystemThemeWatcher)} changed the app theme on initialization.\",\n                nameof(SystemThemeWatcher)\n            );\n            ApplicationThemeManager.ApplySystemTheme(updateAccents);\n        }\n    }\n\n    private static void ObserveLoadedWindow(Window window, WindowBackdropType backdrop, bool updateAccents)\n    {\n        IntPtr hWnd =\n            (hWnd = new WindowInteropHelper(window).Handle) == IntPtr.Zero\n                ? throw new InvalidOperationException(\"Could not get window handle.\")\n                : hWnd;\n\n        if (hWnd == IntPtr.Zero)\n        {\n            throw new InvalidOperationException(\"Window handle cannot be empty\");\n        }\n\n        ObserveLoadedHandle(new ObservedWindow(hWnd, backdrop, updateAccents));\n    }\n\n    private static void ObserveWindowWhenLoaded(\n        Window window,\n        WindowBackdropType backdrop,\n        bool updateAccents\n    )\n    {\n        window.Loaded += (_, _) =>\n        {","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/lepoco/wpfui/blob/ffebacd61058170cf63864b7d5aa730cffff848a/src/Wpf.Ui/Appearance/SystemThemeWatcher.cs#L54-L90","documentation":"Thrown in ObserveLoadedWindow when new WindowInteropHelper(window).Handle returns IntPtr.Zero, meaning the WPF window has no HWND yet. This path is for windows expected to already be loaded, so a zero handle indicates the caller invoked Observe too early or on an uninitialized window.","triggerScenarios":"Calling SystemThemeWatcher.Observe (the synchronous path) on a Window that has not completed its first render pass, so WindowInteropHelper.Handle is still zero. The inline ternary expression throws as soon as the handle compares equal to IntPtr.Zero.","commonSituations":"Watching a window in its constructor, in Window.Initialized (before HWND creation), or a window whose Show has not been called. Also when the visual tree is not yet hooked to a presentation source.","solutions":["Call Observe from the Window.Loaded event (or use ObserveWindowWhenLoaded) so the HWND exists.","Defer watching until IsLoaded is true: SystemThemeWatcher.Watch(window) which hooks Loaded internally when needed.","Ensure the window is actually shown (Show/ShowDialog) before observing it."],"exampleFix":"// before\nSystemThemeWatcher.Observe(window); // in constructor, handle is 0\n\n// after\nwindow.Loaded += (_, _) => SystemThemeWatcher.Observe(window);","handlingStrategy":"validation","validationCode":"if (new WindowInteropHelper(window).Handle == IntPtr.Zero) { /* defer to Loaded/SourceInitialized */ }","typeGuard":"static bool WindowHasHandle(System.Windows.Window w) => w.IsLoaded && new WindowInteropHelper(w).Handle != IntPtr.Zero;","tryCatchPattern":null,"preventionTips":["Observe windows only after Loaded or SourceInitialized.","Use SystemThemeWatcher.Watch which hooks Loaded internally for not-yet-loaded windows.","Ensure the window is shown (Show/ShowDialog) before observing."],"tags":["hwnd","interop","window","lifecycle"],"backgroundTag":null,"analyzedSha":"ffebacd61058170cf63864b7d5aa730cffff848a","analyzedAt":"2026-08-13T21:36:01.370Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}