Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java.Lang.IllegalStateException after MainPage swap #11501

Closed
czmirek opened this issue Nov 19, 2022 · 17 comments · Fixed by #19532
Closed

Java.Lang.IllegalStateException after MainPage swap #11501

czmirek opened this issue Nov 19, 2022 · 17 comments · Fixed by #19532
Assignees
Labels
area-navigation NavigationPage fixed-in-8.0.10 fixed-in-9.0.0-preview.2.10293 platform/android 🤖 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Milestone

Comments

@czmirek
Copy link

czmirek commented Nov 19, 2022

Description

Exception Java.Lang.IllegalStateException is thrown when I try to change the Application.Current.MainPage after the browser opened with WebAuthenticator.Default.AuthenticateAsync is closed without any login.

Steps to Reproduce

  • Checkout the attached repo
  • Go to the example OIDC server https://openidconnect.net/ and copy the generated URL
  • Paste the URL into MainPage.xaml.cs line 16
  • Run app
  • Click the "Login" button
  • Close the browser, do not attempt to login at all
  • Exception is thrown on line 25

Link to public reproduction project repository

https://github.com/czmirek/maui_auth_mainpage_fail

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 12, API 31, x86_64

Did you find any workaround?

Yes, see this commit in another branch of the repo. I figured out that MainActivity.OnResume must run first before MainPage is swapped. It looks like a race condition. The workaround is simple with TaskCompletionSource but I'm not sure if this is going to work in all cases.

Relevant log output

{Java.Lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at Java.Interop.JniEnvironment.InstanceMethods.CallIntMethod(JniObjectReference instance, JniMethodInfo method, JniArgumentValue* args) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:line 11725
at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractInt32Method(String encodedMember, IJavaPeerable self, JniArgumentValue* parameters) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:line 492
at AndroidX.Fragment.App.BackStackRecord.Commit() in /Users/runner/work/1/s/generated/androidx.fragment.fragment/obj/Release/net6.0-android/generated/src/AndroidX.Fragment.App.BackStackRecord.cs:line 131
at Microsoft.Maui.Platform.NavigationRootManager.SetContentView(IView view) in D:\a\_work\1\s\src\Core\src\Platform\Android\Navigation\NavigationRootManager.cs:line 147
at Microsoft.Maui.Platform.NavigationRootManager.Connect(IView view, IMauiContext mauiContext) in D:\a\_work\1\s\src\Core\src\Platform\Android\Navigation\NavigationRootManager.cs:line 88
at Microsoft.Maui.Handlers.WindowHandler.CreateRootViewFromContent(IWindowHandler handler, IWindow window) in D:\a\_work\1\s\src\Core\src\Handlers\Window\WindowHandler.Android.cs:line 79
at Microsoft.Maui.Handlers.WindowHandler.MapContent(IWindowHandler handler, IWindow window) in D:\a\_work\1\s\src\Core\src\Handlers\Window\WindowHandler.Android.cs:line 24
at Microsoft.Maui.PropertyMapper`2.<>c__DisplayClass5_0[[Microsoft.Maui.IWindow, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Handlers.IWindowHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<Add>b__0(IElementHandler h, IElement v) in D:\a\_work\1\s\src\Core\src\PropertyMapper.cs:line 172
at Microsoft.Maui.PropertyMapper.UpdatePropertyCore(String key, IElementHandler viewHandler, IElement virtualView) in D:\a\_work\1\s\src\Core\src\PropertyMapper.cs:line 47
at Microsoft.Maui.PropertyMapper.UpdateProperty(IElementHandler viewHandler, IElement virtualView, String property) in D:\a\_work\1\s\src\Core\src\PropertyMapper.cs:line 72
at Microsoft.Maui.Handlers.ElementHandler.UpdateValue(String property) in D:\a\_work\1\s\src\Core\src\Handlers\Element\ElementHandler.cs:line 87
at Microsoft.Maui.Controls.Window.OnPropertyChanged(String propertyName) in D:\a\_work\1\s\src\Controls\src\Core\HandlerImpl\Window\Window.Impl.cs:line 253
at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 533
at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 469
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 391
at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 365
at Microsoft.Maui.Controls.Window.set_Page(Page value) in D:\a\_work\1\s\src\Controls\src\Core\HandlerImpl\Window\Window.Impl.cs:line 113
at Microsoft.Maui.Controls.Application.set_MainPage(Page value) in D:\a\_work\1\s\src\Controls\src\Core\Application.cs:line 107
at MauiApp1.MainPage.OnCounterClicked(Object sender, EventArgs e) in C:\Users\lesar\source\repos\maui_auth_mainpage_fail\MauiApp1\MainPage.xaml.cs:line 27  --- End of managed Java.Lang.IllegalStateException stack trace ---java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState	at androidx.fragment.app.FragmentManager.checkStateLoss(FragmentManager.java:1601)	at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1641)	at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:341)	at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:306)	at crc6468b6408a11370c2f.WebAuthenticatorIntermediateActivity.n_onResume(Native Method)	at crc6468b6408a11370c2f.WebAuthenticatorIntermediateActivity.onResume(WebAuthenticatorIntermediateActivity.java:41)	at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1476)	at android.app.Activity.performResume(Activity.java:8191)	at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4747)	at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4790)	at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:54)	at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)	at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)	at android.os.Handler.dispatchMessage(Handler.java:106)	at android.os.Looper.loopOnce(Looper.java:201)	at android.os.Looper.loop(Looper.java:288)	at android.app.ActivityThread.main(ActivityThread.java:7839)	at java.lang.reflect.Method.invoke(Native Method)	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)  --- End of managed Java.Lang.IllegalStateException stack trace ---java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState	at androidx.fragment.app.FragmentManager.checkStateLoss(FragmentManager.java:1601)	at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1641)	at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:341)	at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:306)	at crc6468b6408a11370c2f.WebAuthenticatorIntermediateActivity.n_onResume(Native Method)	at crc6468b6408a11370c2f.WebAuthenticatorIntermediateActivity.onResume(WebAuthenticatorIntermediateActivity.java:41)	at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1476)	at android.app.Activity.performResume(Activity.java:8191)	at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4747)	at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4790)	at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:54)	at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)	at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)	at android.os.Handler.dispatchMessage(Handler.java:106)	at android.os.Looper.loopOnce(Looper.java:201)	at android.os.Looper.loop(Looper.java:288)	at android.app.ActivityThread.main(ActivityThread.java:7839)	at java.lang.reflect.Method.invoke(Native Method)	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)}
@czmirek czmirek added the t/bug Something isn't working label Nov 19, 2022
@jsuarezruiz jsuarezruiz added this to the Backlog milestone Nov 21, 2022
@ghost
Copy link

ghost commented Nov 21, 2022

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@czmirek
Copy link
Author

czmirek commented Nov 23, 2022

For anyone finding this, I found this issue is also related to dotnet/sdk#28880 and for the code to work in release, you need to add <AndroidLinkResources>false</AndroidLinkResources> to your MAUI csproj.

@czmirek czmirek closed this as completed Nov 23, 2022
@czmirek
Copy link
Author

czmirek commented Nov 23, 2022

Missclick closed, sorry :(

@czmirek czmirek reopened this Nov 23, 2022
@rkops-bd
Copy link

rkops-bd commented Dec 1, 2022

I have the same issue, when setting a new mainpage when a timer ticks and the user need to re-authenticate.

@jfversluis
Copy link
Member

Looks very similar to #11259

@PureWeen
Copy link
Member

@rkops-bd can you attach a repro? I'm not able to reproduce this with the original posters sample.

@PureWeen
Copy link
Member

@czmirek I was able to reproduce your issue. From my reproduction, it seems like the issue happens because the MainPage swap is happening while the app is stopped so your workaround is waiting for the app to re-resume. That's something we should fix but I'm just leaving a note here with my observations for other people that come across this.

@XamlTest XamlTest added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed labels Jun 7, 2023
@XamlTest
Copy link

XamlTest commented Jun 7, 2023

Verified this on Visual Studio Enterprise 17.7.0 Preview 1.0. Repro on Android 13.0-API33 with provided Project:
MauiApp1.zip

@r-work
Copy link

r-work commented Nov 16, 2023

Anybody who's having trouble with this, here is a workaround, it's not great, but app stopped crashing:

public class App : Microsoft.Maui.Controls.Application
{
    public static bool IsSleeping { get; set; }
    
    protected override void OnStart()
    {
        IsSleeping = false;
        base.OnStart();
    }

    protected override void OnSleep()
    {
        IsSleeping = true;
        base.OnSleep();
    }

    protected override void OnResume()
    {
        IsSleeping = false;
        base.OnResume();
    }

    public void SetMainPage()
    {
       MainThread.BeginInvokeOnMainThread(async () =>
       {
           while (IsSleeping)
           {
               await Task.Delay(500);
           }

           Current.MainPage = new MainPage();
      });
    }
}

@drasticactions
Copy link
Contributor

FYI: #19304

I think this issue invokes the same codepaths as whatever is causing this to fail. Once this issue gets addressed, we should reassess the above issue to verify if it's fixed too (My guess is that it should, since I think it's the same underlying cause). If it's not, we should reopen it.

@datvm
Copy link

datvm commented Dec 8, 2023

I found out that the only workaround to temporarily "fix" it now is setting LaunchMode = LaunchMode.SingleInstance instead of SingleTop.

@PureWeen
Copy link
Member

Possible related #15788

@Gekidoku
Copy link

Forwarding a comment PureWeen made in a possibly related issue
#18159 (comment)

@pulmuone
Copy link

pulmuone commented Feb 1, 2024

I found the cause in Android.
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/app/FragmentManager.java

Error Message : "Can not perform this action after onSaveInstanceState"

private void checkStateLoss() {
    if (mStateSaved) {
        throw new IllegalStateException(
                "Can not perform this action after onSaveInstanceState");
    }
    if (mNoTransactionsBecause != null) {
        throw new IllegalStateException(
                "Can not perform this action inside of " + mNoTransactionsBecause);
    }
}

@VNGames
Copy link

VNGames commented Feb 8, 2024

Even if you just minimize the app while it is on splash screen it will crash (just setting the main page inside of App's constructor. Same if you set it inside IWindowCreator).

@danielftz
Copy link

This seems to only happen when a debugger is attached?

@VNGames
Copy link

VNGames commented Feb 21, 2024

This seems to only happen when a debugger is attached?

No. It crashes on release builds too. and on debug without debugger attached too.
Just open the app and while on the splashscreen minimize it and then return back (maybe wait a few sec before returning back).

It can be fixed by changing commit() to commitAllowingStateLoss() when fragments are switched. And I remember I saw Xamarin does exactly that and it doesn't have such problem. I don't know the consequences of such fix though.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-navigation NavigationPage fixed-in-8.0.10 fixed-in-9.0.0-preview.2.10293 platform/android 🤖 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.