CommunityToolkit / CommunityToolkit/dotnet
AsyncRelayCommand causes InvalidOperation_HandleIsNotInitialized crashes in .NET 10 version of MAUI
- Dominant language
- C#
- Stars
- 3.8k
- Forks
- 400
- PR merge metrics
- No merged PRs in 30d
Description
### Describe the bug
After upgrading MAUI from .NET 9 version to .NET 10 (specifically 10.0.51), random crashes are reported. I'm not able to reproduce it but the crash rate surged for both Android and Windows (I don't release for iOS/Mac).
There are 2 scenarios that causes the crash:
1. **Using any AsyncRelayCommand that prevents concurrent execution (which is the default setting)**. When the command finishes, it runs NotifyCanExecuteChanged internally. That causes IsEnabled property to a Button that uses the command to be updated and that can randomly cause the app to crash with InvalidOperation_HandleIsNotInitialized. **Workaround:** I managed to mitigate the crashes by creating the commands with AsyncRelayCommandOptions.AllowConcurrentExecutions option and preventing concurrent execution manually in my code. It added a lot of boiler plate code so I don't like the solution but it definitelly helped.
2. ** Calling NotifyCanExecuteChanged() in the code** can unfurtunatelly also crash the app. This is less frequent by the first case but it happends. My workaround was to create a helper method that calls NotifyCanExecuteChanged() on an AsyncRelayCommand but encloses the call in a try..catch block silently catching all exceptions and reporting them. Again, not a great solution, but necessary for .NET MAUI to keep the crash rate back on a .NET 9 level.
I'm not sure what was changed and if the problem is in MVVM toolkit or MAUI.
Example of the stack traces:
```
android.runtime.JavaProxyThrowable: [System.InvalidOperationException]: InvalidOperation_HandleIsNotInitialized
at System.WeakReference`1[[Microsoft.Maui.Controls.BindableObject, Microsoft.Maui.Controls, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]].SetTarget + 0x29(Unknown Source:-1)
at Microsoft.Maui.Controls.Internals.TypedBinding`2[[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ApplyToResolvedSource + 0x0(Unknown Source:-1)
at Microsoft.Maui.Controls.Internals.TypedBinding`2[[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Apply + 0xa8(Unknown Source:-1)
at Microsoft.Maui.Controls.BindableObject.ForceBindingApply + 0x27(Unknown Source:-1)
at Microsoft.Maui.Controls.CommandElement.GetCanExecute + 0x43(Unknown Source:-1)
at Microsoft.Maui.Controls.Button.get_IsEnabledCore + 0x8(Unknown Source:-1)
at Microsoft.Maui.Controls.VisualElement.CoerceIsEnabledProperty + 0x16(Unknown Source:-1)
at Microsoft.Maui.Controls.BindableObject.SetValueCore + 0xf7(Unknown Source:-1)
at Microsoft.Maui.Controls.BindableObject.SetValue + 0x55(Unknown Source:-1)
at Microsoft.Maui.Controls.BindableObjectExtensions.RefreshPropertyValue + 0x45(Unknown Source:-1)
at Microsoft.Maui.Controls.VisualElement.RefreshIsEnabledProperty + 0x0(Unknown Source:-1)
at Microsoft.Maui.Controls.Button.Microsoft.Maui.Controls.Internals.ICommandElement.CanExecuteChanged + 0x0(Unknown Source:-1)
at Microsoft.Maui.Controls.WeakCommandSubscription+CommandCanExecuteSubscription.CanExecuteChanged + 0x2c(Unknown Source:-1)
at Unknown.Unknown(Unknown Source:-1)
at CommunityToolkit.Mvvm.Input.AsyncRelayCommand`1+<g__MonitorTask|22_0>d[[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext + 0x111(Unknown Source:-1)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw + 0x11(Unknown Source:-1)
at System.Threading.Tasks.Task+<>c.b__124_0 + 0x0(Unknown Source:-1)
at Android.App.SyncContext+<>c__DisplayClass2_0.b__0 + 0x0(Unknown Source:-1)
at Java.Lang.Thread+RunnableImplementor.Run + 0x8(Unknown Source:-1)
at Java.Lang.IRunnableInvoker.n_Run + 0x16(Unknown Source:-1)
at mono.java.lang.RunnableImplementor.n_run(RunnableImplementor.java:-2)
at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:21)
at android.os.Handler.handleCallback(Handler.java:995)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loopOnce(Looper.java:273)
at android.os.Looper.loop(Looper.java:363)
at android.app.ActivityThread.main(ActivityThread.java:10060)
at java.lang.reflect.Method.invoke(Method.java:-2)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
```
### Regression
Not sure. It used to work in .NET 9 version of MAUI and started to crash aftter upgrading to .NET 10.
### Steps to reproduce
I cannot reproduce it locally. The AppCenter reports that the app crashes sometimes after an hour if its usage, sometimes just in a few minutes. The crashes are random but too frequent to be ignored.
### Expected behavior
No crashes as with the .NET 9 version of MAUI
### Screenshots
_No response_
### IDE and version
Other
### IDE version
VS2026 (18.5.2)
### Nuget packages
- [ ] CommunityToolkit.Common
- [ ] CommunityToolkit.Diagnostics
- [ ] CommunityToolkit.HighPerformance
- [x] CommunityToolkit.Mvvm (aka MVVM Toolkit)
### Nuget package version(s)
8.4.2
### Additional context
_No response_
### Help us help you
No, just wanted to report this
Contributor guide
Assessment
This issue has not been assessed yet.