dotnet / dotnet/maui

[9.0.100, Windows] App crashes with some users to Window was already deactivated

Open
#31,315 7 comments 0 reactions 0 assignees View on GitHub
area-controls-window platform/windows t/bug
Dominant language
C#
Stars
23.3k
Forks
2k
Avg merge
1d 15h
Merged PRs (30d)
290

Description

### Description

Sentry reports for my game GnollHack that for some users on Windows the app crashes in System.InvalidOperationException - Window was already deactivated. I just upgraded to .NET 9.0.8 and .NET MAUI 9.0.100 hoping that this would fix the problem, but it didn't, so it is probably best to file the issue here. The reported stack trace is as follows:

```
Window.cs in void Window.Microsoft.Maui.IWindow.Deactivated() at line 519

void IWindow.Deactivated()
{
if (!IsActivated)
throw new InvalidOperationException("Window was already deactivated");
IsActivated = false;
Deactivated?.Invoke(this, EventArgs.Empty);
OnDeactivated();
}
Assembly: Microsoft.Maui.Controls
Version: 1.0.0.0

AppHostBuilderExtensions.Windows.cs in void AppHostBuilderExtensions.OnConfigureLifeCycle(IWindowsLifecycleBuilder windows)+(Window window, WindowActivatedEventArgs args) => { } [2] at line 35

LifecycleEventServiceExtensions.cs in void LifecycleEventServiceExtensions.InvokeLifecycleEvents(IServiceProvider services, Action action) at line 31

MauiWinUIWindow.cs in void MauiWinUIWindow.OnActivated(object sender, WindowActivatedEventArgs args) at line 91

TypedEventHandler EventState.GetEventInvoke()+(object sender, WindowActivatedEventArgs args) => { }

int Windows_Foundation_TypedEventHandler_2_object__Microsoft_UI_Xaml_WindowActivatedEventArgs.Do_Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr args)

Assembly: Microsoft.WinUI
Version: 3.0.0.0
```

ChatGPT 5 explained the problem based on my stack trace as follows (take with a grain of salt):

**What the stack trace shows**

The call is happening inside Window.Microsoft.Maui.IWindow.Deactivated().

That method explicitly throws if IsActivated is already false.

```
if (!IsActivated)
throw new InvalidOperationException("Window was already deactivated");
```

The call path is:

`OnActivated → LifecycleEventServiceExtensions.InvokeLifecycleEvents → IWindow.Deactivated()`

Which means: MAUI thinks it’s activating or deactivating a window, but the activation state being reported by WinUI’s WindowActivated event is inconsistent with MAUI’s internal flag.

**Why it happens**

On Windows, WinUI raises Window.Activated events for different reasons:

```
WindowActivationState.CodeActivated

WindowActivationState.PointerActivated

WindowActivationState.Deactivated
```

Sometimes, in quick succession, WinUI may raise multiple Deactivated events without a corresponding Activated in between (e.g., when switching virtual desktops, locking/unlocking, multiple monitor setups, alt-tabbing quickly).

MAUI’s Window object keeps its own IsActivated flag, but it assumes WinUI’s events will always alternate cleanly (activate → deactivate → activate → …). That’s not always true in practice.

Result: MAUI tries to deactivate an already-deactivated window → InvalidOperationException.

### Steps to Reproduce

This is just a Sentry report happening for a fraction of users on Windows, so not sure how to reproduce. Probably depends on how they use the app (switching between apps quickly etc.)

### Link to public reproduction project repository

https://github.com/hyvanmielenpelit/GnollHack

### Version with bug

9.0.100 SR10

### Is this a regression from previous behavior?

Not sure, did not test other versions

### Last version that worked well

Unknown/Other

### Affected platforms

Windows

### Affected platform versions

Windows 10.0.26100.4946

### Did you find any workaround?

No

### Relevant log output

```shell

```

Contributor guide

Open the contributing guide

Research direction

Start with Window.cs at line 519 and AppHostBuilderExtensions.Windows.cs at line 35, then follow the reported path through MauiWinUIWindow.OnActivated and LifecycleEventServiceExtensions.InvokeLifecycleEvents. Use the GnollHack reproduction project and Windows activation events to investigate the inconsistent state. Done means the reported activation sequence no longer crashes with "Window was already deactivated".

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
desktop, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.