Repository navigation
Description
Description
On Android, Permissions.RequestAsync<T>() appears to add a pending permission request to an internal static request table before validating that the call is running on the main thread. If the API is called from a background thread while the permission is not already granted, it throws the expected PermissionException, but the pending request entry is left behind because no Android permission request was launched and OnRequestPermissionsResult will never be called.
In normal app code, this is fairly unlikely to become user-visible. A single invalid off-main-thread call only leaks a small pending request entry for the lifetime of the process. The more serious failure mode requires repeated bad calls, such as a retry loop, startup/resume loop, or background helper that catches and swallows the exception.
However, once enough stale entries accumulate, MAUIβs Android permission request-code ring can wrap and collide with the stale entries. At that point, even a valid main-thread permission request can fail before Android is asked to show the permission prompt.
This is worth tracking as a known issue because runaway invalid permission-request code can put the app process into a poisoned state where subsequent MAUI permission requests fail until the app process is restarted.
Steps to Reproduce
Steps To Reproduce
-
Create a new .NET MAUI Android app.
-
Add a runtime permission to
Platforms/Android/AndroidManifest.xml, for example:
<uses-permission android:name="android.permission.CAMERA" />- Make sure the permission is not already granted for the app.
adb shell pm revoke <package-name> android.permission.CAMERA- From app code, repeatedly call
Permissions.RequestAsync<T>()from a background thread and swallow the expected exception:
for (var i = 0; i < 999; i++)
{
try
{
await Task.Run(() => Permissions.RequestAsync<Permissions.Camera>());
}
catch (PermissionException)
{
// Expected: "Permission request must be invoked on main thread."
}
}- After the loop finishes, request the same permission normally from the main thread:
await Permissions.RequestAsync<Permissions.Camera>();Expected Result
The main-thread permission request should either show the Android permission prompt or return the current permission status.
Actual Result
The main-thread request fails before Android is asked to show a permission prompt:
System.ArgumentException: An item with the same key has already been added. Key: 12001
The failed background-thread calls leave entries in MAUIβs static Android permission-request table. After enough failures, the request-code ring wraps and later valid permission requests collide with stale entries.
Link to public reproduction project repository
No response
Version with bug
10.0.70
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
Unknown/Other
Affected platforms
Android
Affected platform versions
No response
Did you find any workaround?
No response
Activity
nivetha-nagalingam commentedon Jun 11, 2026
This issue has been validated in Visual Studio Code 1.124.0 with .NET MAUI versions 10.0.0 , 10.0.70 10.0.71. It can be reproducible on Android platform.
PermissionIssue 1.zip
Screen.Recording.2026-06-11.at.4.11.20.PM.mov
jpd21122012 commentedon Aug 3, 2026
I investigated this issue and was able to reproduce it on the current
mainbranch (.NET MAUI 10.0.90).I have submitted a PR with a minimal fix that validates the main thread before registering the pending permission request, preventing stale entries from being added after off-main-thread failures.
The PR also includes Android device tests covering this regression.
Linked PR: #37056
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
3 remaining items
Publish reproduction evidence for #35861 on android
Publish reproduction evidence for #35861 on android
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦
Fix stale Android permission requests after off-main-thread failures (#β¦