Skip to content

IllegalStateException: Reply already submitted crash in currentAccountCallback after clearing app data #116

@pedrocampota

Description

@pedrocampota

Issue description

In the currentAccountCallback implementation of the Android side of the msal_auth plugin, calling publicClientApplication.checkCurrentAccount(...) can trigger multiple callbacks when there is no account in cache (e.g. immediately after clearing the app’s data). Specifically, MSAL may invoke:

  1. onAccountLoaded(null)
  2. Followed by either onAccountChanged(priorAccount, null) or onError(...)

Each of these callback methods calls into the same MethodChannel.Result—either via result.success(...) (for a missing account) or result.error(...)—which causes Flutter to throw:

java.lang.IllegalStateException: Reply already submitted at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:431) at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:272) ...

This crash originates from plugins/msal_auth/android/src/main/kotlin/com/example/msal_auth/MsalAuth.kt, in the currentAccountCallback function:

internal fun currentAccountCallback(result: MethodChannel.Result): CurrentAccountCallback {
    return object : CurrentAccountCallback {
        override fun onAccountLoaded(activeAccount: IAccount?) {
            if (activeAccount == null) {
                setNoCurrentAccountException(result)      // 1st reply
                return
            }
            result.success(getCurrentAccountMap(activeAccount))
        }

        override fun onAccountChanged(priorAccount: IAccount?, currentAccount: IAccount?) {
            if (currentAccount == null) {
                setNoCurrentAccountException(result)      // 2nd reply → crash
                return
            }
            result.success(getCurrentAccountMap(currentAccount))
        }

        override fun onError(exception: MsalException) {
            setMsalException(exception, result)           // could be another reply
        }
    }
}

Steps to Reproduce:

  1. Add msal_auth v3.2.6 to a Flutter Android app.
  2. Authenticate once to populate the account cache.
  3. In Android Settings → Apps → YourApp → Storage, tap “Clear data”.
  4. Relaunch the app; on startup it invokes getCurrentAccount (which calls checkCurrentAccount).
  5. The app crashes immediately with the IllegalStateException: Reply already submitted.

Expected Behavior:
checkCurrentAccount (and thus currentAccountCallback) should only send one response back to Dart—either a null account (or a specific client exception) or an error—without throwing an exception when multiple MSAL callbacks occur.

MSAL Auth Plugin Version

3.2.6

Platforms

  • Android
  • iOS
  • MacOS

Account Mode

Single

Android JSON Configuration

Minimal Dart Code Snippet

.

Relevant log output

Before submitting, please confirm

  • I have checked the documentation and it does not solve my issue.
  • I have run the example app and the issue still exists.

Flutter Doctor Output

[√] Flutter (Channel stable, 3.32.5, on Microsoft Windows [Version 10.0.26100.4652], locale pt-PT)
[√] Windows Version (11 Home 64-bit, 24H2, 2009)
[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[√] Chrome - develop for the web
[X] Visual Studio - develop Windows apps
    X Visual Studio not installed; this is necessary to develop Windows apps.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default components
[!] Android Studio (version 2022.3)
    X Unable to determine bundled Java version.
[√] Android Studio (version 2025.1.1)
[√] VS Code (version 1.102.0)
[√] Connected device (4 available)
[√] Network resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds more infoIssue lacks necessary details

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions