java.lang.IllegalArgumentException: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent means an Android app targeting API level 31 or higher created a PendingIntent without declaring its mutability. This occurs at runtime when the PendingIntent is created. The safest first action is to inspect the stack trace and identify the exact factory call before changing any flags; if app code owns it and no fill-in behavior is required, preserve the existing flags and add FLAG_IMMUTABLE.
What the “Targeting S+” PendingIntent error means
Android’s PendingIntent mutability requirement applies when an app targeting Android 12/API level 31 or higher calls PendingIntent.getActivity(), getActivities(), getBroadcast(), getService(), or getForegroundService() without either explicit mutability flag.
FLAG_IMMUTABLE and FLAG_MUTABLE are alternatives; do not combine them. Android recommends immutable PendingIntents in most cases. Mutability is appropriate only when a receiver or Android API must modify unfilled fields in the wrapped Intent. The PendingIntent API reference also distinguishes these mutability declarations from behavioral flags such as FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT, and FLAG_ONE_SHOT.
This runtime exception is not the separate Android 12 android:exported requirement, which concerns component declarations in the manifest.
Find the PendingIntent call that actually throws the exception
The exception message identifies the missing declaration but does not identify whether application code, generated code, or a bundled library owns the call.
- Start at the
java.lang.IllegalArgumentExceptionin the complete stack trace. - Locate the first relevant non-framework frame associated with one of the PendingIntent factory methods.
- Match that frame to its package, module, generated component, or bundled dependency.
- Record the factory method, request code, wrapped Intent, and complete flags expression.
- Classify the call as application-owned, generated, or dependency-owned before selecting a repair.
Do not edit an unrelated PendingIntent merely because it is visible in app code. If the relevant frame belongs to a dependency, an app-level flag change elsewhere may leave the failing implementation untouched.
Fix app code with FLAG_IMMUTABLE by default
When this applies: Use this path when app code owns the factory call and no sender, receiver, or Android API needs to modify unfilled fields of the wrapped Intent.
Prerequisites: Identify the exact call and retain its existing request code, Intent, factory method, and behavioral flags. Adding FLAG_IMMUTABLE must not remove FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT, FLAG_ONE_SHOT, or another required existing flag.
- Keep the current request code and Intent unchanged.
- Combine
FLAG_IMMUTABLEwith the existing flags using Kotlinoror Java|. - Create the PendingIntent with the combined expression.
- Reproduce the feature that sends it.
Kotlin example
Before:
PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags)
After:
PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags or PendingIntent.FLAG_IMMUTABLE)
Java example
Before:
PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags)
After:
PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags | PendingIntent.FLAG_IMMUTABLE)
Expected result: The factory call now supplies the required mutability declaration. The affected notification action, activity launch, alarm, widget, callback, or service launch must still be tested to confirm that its behavior remains intact. An immutable PendingIntent can still be updated by its creator using FLAG_UPDATE_CURRENT.
Risk and rollback: This is a low-risk code change with no documented data-loss risk. If testing proves that the receiver or platform API requires fill-in behavior, revert only the added immutable declaration and evaluate the narrow mutable path below.
Use FLAG_MUTABLE only when the feature requires fill-in behavior
When this applies: Use FLAG_MUTABLE only when documented functionality must modify the wrapped Intent, including inline replies, bubbles, location callbacks, repeating-alarm count extras, or another required fill-in operation.
| Requirement | Declaration |
|---|---|
| No receiver or platform mutation is required | FLAG_IMMUTABLE |
| A documented feature must supply fill-in data | FLAG_MUTABLE |
Prerequisites: Verify the mutation requirement for the affected feature. Preserve all required behavioral flags, and use an explicit base Intent with its action, package, and component set where possible.
- Keep the existing request code, factory type, and required behavioral flags.
- Add
FLAG_MUTABLEinstead ofFLAG_IMMUTABLE. - Make the base Intent explicit where possible.
- Retest the exact operation that needs fill-in behavior.
- Confirm that only the documented fields need to remain fillable.
Kotlin example
PendingIntent.getActivity(context, existingRequestCode, explicitIntent, existingFlags or PendingIntent.FLAG_MUTABLE)
Java example
PendingIntent.getActivity(context, existingRequestCode, explicitIntent, existingFlags | PendingIntent.FLAG_MUTABLE)
Expected result: The factory call declares mutability while retaining the existing behavioral flags, and the documented receiver or platform fill-in operation remains available.
Risk and rollback: This is a medium-risk security decision, although it has no documented data-loss risk. A mutable PendingIntent delegates control over unfilled Intent fields, so applying it broadly can increase exposure. Follow the official Android PendingIntent security guidance, prefer an explicit base Intent, and replace FLAG_MUTABLE with FLAG_IMMUTABLE if the fill-in dependency is removed. The same least-privilege principle is relevant when reviewing secure inter-app URI sharing on Android.
Handle a PendingIntent created by a dependency
If the first relevant stack-trace frame belongs to generated code or a bundled SDK, changing an unrelated application-owned PendingIntent is not a confirmed fix. Dependency remediation is project-specific and must be verified against primary documentation for the owning artifact.
- Map the owning package or module from the stack trace to the exact bundled artifact.
- Check that artifact’s primary release documentation for a maintained release that explicitly addresses Android 12 PendingIntent compatibility.
- If such a release is documented, update only through the project’s established dependency process.
- Inspect the resolved dependency graph to confirm that the intended artifact was selected rather than an older transitive version.
- Rebuild the app and reproduce the same feature.
- Confirm that the corrected implementation is packaged and that the original missing-mutability call no longer appears.
Expected result: If the verified dependency release contains the repair and the rebuilt app resolves that release, the dependency-owned factory call should supply an explicit mutability declaration. This outcome cannot be assumed from the requested version alone.
Risk and rollback: Dependency changes can alter behavior outside the failing feature. Review the dependency’s release information and restore the prior project dependency state if the update introduces a regression. No universal dependency name or corrected version is established for this exception.
Use PendingIntentCompat when compatibility handling is appropriate
When this applies: Use AndroidX PendingIntentCompat when app code supports platform versions where the compatibility helper is preferred and the caller can still state whether the PendingIntent is mutable.
Prerequisites: Confirm that the project’s AndroidX Core version contains PendingIntentCompat, identify the original factory type, and decide mutability from the feature’s actual requirements.
- Choose the helper corresponding to the original operation:
getActivity,getBroadcast,getService, orgetForegroundService. - Pass the existing non-mutability behavioral flags to the helper.
- Set
isMutableto false unless a verified mutation requirement applies. - Keep the request code and wrapped Intent behavior unchanged.
- Test on the affected Android 12+ target configuration.
Expected result: The compatibility helper combines the caller’s explicit mutability decision with the existing flags as required on supported platform versions.
Risk and rollback: This is a low-risk compatibility path with no documented data-loss risk, but changing helper APIs can affect call structure. Return to the matching framework factory while retaining an explicit mutability flag if the helper change causes a regression.
Verify the repair without changing PendingIntent behavior
- Run the rebuilt app with a target SDK of API level 31 or higher and reproduce the original trigger.
- Confirm that the exact
Targeting S+exception no longer occurs at the identified factory call. - Retest the affected notification tap or action, alarm, widget, callback, activity launch, or service launch.
- If
FLAG_UPDATE_CURRENT,FLAG_CANCEL_CURRENT, orFLAG_ONE_SHOTwas present, verify its original update, cancellation, or one-shot behavior. - For a mutable PendingIntent, verify only the required fill-in behavior and confirm that the base Intent is explicit where possible.
- For a dependency repair, confirm that the resolved and packaged artifact is the verified release rather than relying only on the requested dependency declaration.
A successful build alone does not prove that the runtime path is repaired. Also keep Android 14/API 34 mutable implicit-PendingIntent restrictions separate: they produce a different error condition and are not resolved by this API level 31 procedure.

