You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
"Data intent is null" if we exit the application and open it again using the icon #1094
We hit this in production and spent a while on it, so here is what we measured on an Android 15 emulator. Two things that may save someone else the time.
The singleTop workaround in the issue body makes it worse, not better.
We tried it. The error goes away, but the flow then neither resolves nor rejects — the promise just hangs forever. From the user's side that is a login that silently does nothing, which is harder to diagnose and worse UX than an error. We also tried android:alwaysRetainTaskState="true" on the launcher activity: no effect at all, it does not override singleTask's clear-top behaviour.
The root cause is two independent problems, and fixing either alone does nothing.
The task stack tells it:
before: AuthorizationManagementActivity <- holds the pending request
MainActivity
(return to the app from the launcher)
after: MainActivity
AppAuth: No stored state - unable to handle response
AppAuth keeps the pending request inside AuthorizationManagementActivity, which lives in the caller's task. With MainActivity as singleTask, re-entering from the launcher clears the task above the root and destroys it. Even if the response is delivered perfectly, AppAuth has nothing to match it against — hence No stored state.
authorizeWithConfiguration delivers via startActivityForResult(authIntent, 52), which is bound to the living activity instance and cannot cross tasks. When the activity is gone the result arrives as a null Intent, which is where Data intent is null comes from.
What worked for us, keeping singleTask on MainActivity so React Native deep linking stays intact:
App side: give AuthorizationManagementActivity its own taskAffinity plus launchMode="singleInstance", so the app's task reset never touches it.
Library side: deliver the response through a PendingIntent addressed to the launcher activity — component only, no MAIN/LAUNCHER categories, since those are what trigger the reset — and complete the flow from onNewIntent, which the module declares but leaves empty today.
After that the pending request survives the round trip and the response reaches JS normally. Verified twice in a row, and we checked that psb://-style deep links and universal links still resume a single MainActivity instance rather than spawning a second.
Happy to open a PR for the library half if maintainers think the PendingIntent path is the right direction. It would need a decision on whether to make it opt-in, since it changes how the response arrives.
Correction to my earlier comment here — I proposed a direction, tried it in production, and it did not survive contact with real devices. Closing the PR I opened (#1137), and recording why so nobody repeats it.
The PendingIntent approach makes things worse on the devices that actually hit this bug. It requires the app to launch itself from the background, which Android permits only briefly after the app loses focus, and which OEM skins restrict much harder. Measured on an Oppo A74 (Android 14, ColorOS, stock settings):
Provider
Result
Spotify (mails a one-time code)
Never completes — the mail round trip outlasts the allowance, and the promise never settles at all
Google (fast)
Completes, getting in under the wire
Spotify with ColorOS "auto-launch" on
Completes — confirming the mechanism
So it converts Data intent is null, which you can at least catch, into an unobservable hang. That is a downgrade.
And the host-app half I suggested — singleInstance plus a separate taskAffinity — breaks retrying. It does keep the activity alive across a task reset, but a second authorization can then never create a fresh instance: Android reuses the stale one, AppAuth reads the resume as a cancellation, and the browser never opens. Abandoning a login and trying again stops working. No emulator surfaced this; it took an explicit retry test on top of the fix.
What worked for us, without touching the library: treat this as an interruption rather than a failure. Track that a flow is in the air, clear it on every settled path, and offer to resume when either Data intent is null arrives or the app comes back to the front with the flow still unsettled. Restarting the authorization is cheap because the provider session is still alive in the browser. It does not make the interruption invisible, but it needs no OEM permission and it does not break retrying.
The underlying issue in this ticket is still real — I just no longer think the fix belongs where I first put it.
Activity
dparcerisa commentedon Aug 31, 2026
We hit this in production and spent a while on it, so here is what we measured on an Android 15 emulator. Two things that may save someone else the time.
The
singleTopworkaround in the issue body makes it worse, not better.We tried it. The error goes away, but the flow then neither resolves nor rejects — the promise just hangs forever. From the user's side that is a login that silently does nothing, which is harder to diagnose and worse UX than an error. We also tried
android:alwaysRetainTaskState="true"on the launcher activity: no effect at all, it does not overridesingleTask's clear-top behaviour.The root cause is two independent problems, and fixing either alone does nothing.
The task stack tells it:
AppAuth keeps the pending request inside
AuthorizationManagementActivity, which lives in the caller's task. WithMainActivityassingleTask, re-entering from the launcher clears the task above the root and destroys it. Even if the response is delivered perfectly, AppAuth has nothing to match it against — henceNo stored state.authorizeWithConfigurationdelivers viastartActivityForResult(authIntent, 52), which is bound to the living activity instance and cannot cross tasks. When the activity is gone the result arrives as a null Intent, which is whereData intent is nullcomes from.What worked for us, keeping
singleTaskonMainActivityso React Native deep linking stays intact:AuthorizationManagementActivityits owntaskAffinitypluslaunchMode="singleInstance", so the app's task reset never touches it.PendingIntentaddressed to the launcher activity — component only, no MAIN/LAUNCHER categories, since those are what trigger the reset — and complete the flow fromonNewIntent, which the module declares but leaves empty today.After that the pending request survives the round trip and the response reaches JS normally. Verified twice in a row, and we checked that
psb://-style deep links and universal links still resume a singleMainActivityinstance rather than spawning a second.Happy to open a PR for the library half if maintainers think the
PendingIntentpath is the right direction. It would need a decision on whether to make it opt-in, since it changes how the response arrives.dparcerisa commentedon Sep 1, 2026
Correction to my earlier comment here — I proposed a direction, tried it in production, and it did not survive contact with real devices. Closing the PR I opened (#1137), and recording why so nobody repeats it.
The
PendingIntentapproach makes things worse on the devices that actually hit this bug. It requires the app to launch itself from the background, which Android permits only briefly after the app loses focus, and which OEM skins restrict much harder. Measured on an Oppo A74 (Android 14, ColorOS, stock settings):So it converts
Data intent is null, which you can at least catch, into an unobservable hang. That is a downgrade.And the host-app half I suggested —
singleInstanceplus a separatetaskAffinity— breaks retrying. It does keep the activity alive across a task reset, but a second authorization can then never create a fresh instance: Android reuses the stale one, AppAuth reads the resume as a cancellation, and the browser never opens. Abandoning a login and trying again stops working. No emulator surfaced this; it took an explicit retry test on top of the fix.What worked for us, without touching the library: treat this as an interruption rather than a failure. Track that a flow is in the air, clear it on every settled path, and offer to resume when either
Data intent is nullarrives or the app comes back to the front with the flow still unsettled. Restarting the authorization is cheap because the provider session is still alive in the browser. It does not make the interruption invisible, but it needs no OEM permission and it does not break retrying.The underlying issue in this ticket is still real — I just no longer think the fix belongs where I first put it.