</>CodeWithKarani

Flutter 'Execution failed for task :app:processDebugResources': Find the Real Error

Karani GeoffreyKarani Geoffrey7 min read

You run flutter build apk, it churns for a minute, and then it stops on this:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:processDebugResources'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > Android resource linking failed

You did not touch a single resource file. You changed one line of Dart, or you added a plugin, or you did nothing at all and it worked yesterday. So you paste the error into a search box and get twenty different answers, each swearing that their fix is the one: delete the build folder, invalidate caches, downgrade Gradle, add a theme, change your compile SDK. Some commenter says it fixed it for them. It will not fix it for you, because this error is not one problem.

Execution failed for task ':app:processDebugResources' is a wrapper. It is Gradle telling you the name of the task that died, not the reason it died. The real error is one layer down, produced by AAPT2, the Android Asset Packaging Tool, and Flutter hides it by default. Every minute you spend trying random fixes without reading that underlying message is a minute wasted guessing.

Do not fix processDebugResources directly. Surface the real AAPT2 error first:

flutter build apk --verbose
# or, from the android/ directory:
./gradlew assembleDebug --stacktrace

Scroll up from the failed-task line to the AAPT2 message. It names a file and reason: a missing resource, a malformed XML, or a Support Library plugin clashing with AndroidX. Fix that. On current toolchains, android.enableJetifier=true is no longer the answer; update the offending plugin instead.

Step 1: Make the real error visible

Flutter's default output swallows the Gradle detail. Turn it back on. Two equivalent ways:

# From the project root
flutter build apk --verbose 2>&1 | tee build.log

# Or drop into the Android project directly, which is often cleaner output
cd android
./gradlew assembleDebug --stacktrace --info

Now search the output for the line that AAPT2 actually emitted. It will look like one of these, and this is the text you fix:

error: resource style/Theme.AppCompat.Light.NoActionBar not found.

error: attribute android:requestLegacyExternalStorage not found.

AAPT: error: '@mipmap/ic_launcher' not found.

ERROR: /path/build/.../AndroidManifest.xml:12: AAPT: error: unexpected element <foo> found in <manifest><application>.

That single line tells you which of the completely unrelated root causes you are actually dealing with. Everything below is organised by what that message says.

Gradle: Execution failed for task ':app:processDebugResources' (the wrapper you see) AAPT2: Android resource linking failed (the real error, one layer down) Cause A Plugin still on the old Support Library, clashing with AndroidX Cause B Malformed or duplicate XML in res/, or a bad values file Cause C Manifest references a resource or attribute that does not exist
One task name, three unrelated failures. Reading the AAPT2 line is what tells you which column you are in.

Cause A: a plugin still on the old Support Library

Message looks like: resource style/Theme.AppCompat... not found, or errors mentioning android.support.* classes. Modern Flutter apps use AndroidX. If a plugin you depend on still references the legacy Android Support Library, its resources and your app's resources cannot link together, and AAPT2 fails.

The advice you will find everywhere is to add android.enableJetifier=true to gradle.properties so Jetifier translates the old library to AndroidX at build time. On current toolchains this advice is stale and can itself break your build. Jetifier is deprecated, and Android Gradle Plugin 8 and 9 no longer support android.enableJetifier or android.useAndroidX=false; AGP 9 treats setting those properties as an error. If your project is on a recent Flutter and AGP, deleting those lines is more likely to help than adding them.

The durable fix is to stop shipping the old library at all:

  1. Find the offending plugin. The AAPT2 message or the dependency tree names it. Run ./gradlew app:dependencies --configuration debugRuntimeClasspath from android/ and look for com.android.support:* entries. Anything under that group is legacy.
  2. Update it. In pubspec.yaml, move to a version of the plugin that is AndroidX-native. Most maintained plugins migrated years ago; you are usually pinned to an old one.
  3. If the plugin is abandoned, replace it or fork it. There is no supported way to keep a Support Library plugin alive on AGP 9.

If, and only if, you are on an older AGP (7.x) where Jetifier still works and updating the plugin is genuinely not an option yet, then the legacy pair is android.useAndroidX=true with android.enableJetifier=true in gradle.properties. Treat it as a temporary bridge on old toolchains, not a fix, and note that it disappears the moment you upgrade AGP.

Cause B: a malformed or duplicate resource

Message points at a specific file and line in res/, for example values/colors.xml:8: error: ... or duplicate value for resource 'string/app_name'. This one is mechanical: AAPT2 is telling you exactly where the bad XML is.

  1. Open the named file at the named line.
  2. Common offenders: an unescaped & or < in a string, a colour value missing its #, a duplicate resource name across two files, or a stray element the schema does not allow.
  3. If you recently added an app icon or splash asset, check that the referenced @mipmap/ic_launcher or @drawable/... actually exists in every density folder it is referenced from.

A frequent Flutter-specific variant: a plugin injects a resource that collides with one of yours, or an icon generator wrote a malformed adaptive-icon XML. The line number is not lying; go read it.

Cause C: the manifest references something that does not exist

Message looks like attribute android:... not found or resource ... referenced from AndroidManifest.xml not found. Your AndroidManifest.xml points at a string, style, or attribute that was never defined, or that requires a higher compile SDK than you are building against.

  1. Open android/app/src/main/AndroidManifest.xml.
  2. Find the attribute or resource named in the error. A @string/... that is not in strings.xml, a @style/... that does not exist, or an attribute like android:requestLegacyExternalStorage that needs compileSdkVersion raised.
  3. Either define the missing resource, or raise compileSdk in android/app/build.gradle so the newer attribute is known to the compiler. Flutter typically wants compileSdk to match the highest requirement across your plugins.

Force a version, do not blindly delete plugins

When two plugins drag in conflicting versions of the same Android library and AAPT2 links against the wrong one, the guess-and-remove approach is slow and destructive. Pin the version instead. In android/app/build.gradle:

configurations.all {
    resolutionStrategy {
        // Force one consistent version instead of letting Gradle pick
        force 'androidx.core:core:1.13.1'
    }
}

This is surgical: it resolves the specific conflict the dependency tree revealed, without ripping out a plugin you actually need. Use the version the AAPT2 error and ./gradlew app:dependencies point you toward.

Verification

You have fixed the right thing when the underlying AAPT2 message is gone, not just when the wrapper stops appearing on one machine. Prove it:

flutter clean
flutter pub get
flutter build apk --debug --verbose 2>&1 | grep -i "aapt\|resource linking"

A clean build with no AAPT2 lines in the output is the real pass. Then build the variant you actually ship:

flutter build apk --release

If release now succeeds too, the fix was structural. If release still fails on the same task, you fixed a symptom on one variant; go back and read the release build's AAPT2 line, which may differ.

What people get wrong

Treating the task name as the error. Ninety percent of the bad advice for this problem exists because people never read past processDebugResources. The task name is identical for three unrelated bugs, so any fix that ignores the AAPT2 line is a coin flip. Read the line.

Reaching for android.enableJetifier=true in 2026. This was reasonable advice on AGP 7 and earlier. On AGP 8 and 9 it is deprecated to removed, and on AGP 9 setting it can fail the build outright. Copying a five-year-old Stack Overflow answer here actively makes things worse. Update the plugin, do not translate it.

Nuking the build and calling it fixed. flutter clean and deleting ~/.gradle/caches resolves exactly one class of this error: a genuinely corrupt cache. It does nothing for a Support Library conflict or a malformed resource, and when it appears to work it is usually because you changed something else at the same time. If clean fixes it, fine, but confirm the AAPT2 line is actually gone rather than assuming.

When it is still broken

  1. Bisect your plugins. If you cannot tell which dependency introduced the old library, comment out half your plugins in pubspec.yaml, build, and narrow down. It is faster than staring at the dependency tree when several plugins are suspect. The same rebuild-and-narrow discipline applies to the React Native version mismatch problem.
  2. Check your Java/JDK and AGP compatibility. A newer AGP needs a newer JDK. A mismatch there can surface as resource-processing failures that look like this one. Run flutter doctor -v and confirm the Android toolchain is consistent.
  3. Read the full AAPT2 dump with --info. Some resource failures only print the useful detail at info level. If --stacktrace alone is not enough, add --info and search for AAPT2.
  4. Confirm the resource exists in the merged manifest. Open build/app/intermediates/merged_manifest/ to see what actually got merged from all your plugins. A resource you think you defined may be shadowed or overridden by a plugin's manifest.

Once you are shipping cleanly, the next wall most Flutter teams hit is the store review itself; that is a different kind of umbrella rejection, and I broke it down in why Guideline 2.3.1 rejections are rarely about your text. The pattern is the same as here: the message you are shown is not the message that matters. Read one layer down.

Frequently asked questions

What does 'Execution failed for task :app:processDebugResources' actually mean?
It means the Android resource compiler AAPT2 failed while linking your app's resources, but Gradle only shows you the name of the task that failed, not why. It is an umbrella error covering unrelated causes: a plugin on the old Support Library, a malformed XML resource, or a missing resource referenced from the manifest. You must re-run with --stacktrace or --verbose to see the real AAPT2 message.
How do I see the real error under processDebugResources?
Run flutter build apk --verbose, or from the android directory run ./gradlew assembleDebug --stacktrace. Scroll up from the task-failed line to find the AAPT2 output, which names the specific file and line, for example 'resource style/Theme.AppCompat not found' or 'error: attribute android:foo not found'. That message, not the task name, is what you fix.
Is 'android.enableJetifier=true' still the fix for AndroidX conflicts?
Not on current toolchains. Jetifier is deprecated and Android Gradle Plugin 8 and 9 no longer support android.enableJetifier or android.useAndroidX=false; setting them can now break the build. The durable fix is to update or replace the plugin that still ships the old Support Library so it is AndroidX-native, rather than translating it at build time.
Why does it say processDebugResources when I am building a release?
Flutter and Gradle still assemble debug resources as part of many build flows, and plugin or resource problems surface under the debug variant task first. The cause is not that you are in debug mode; it is a resource-linking failure that happens to be reported against the debug resource task. Fix the underlying AAPT2 error and both variants build.
#Flutter#Android#Gradle#AAPT2#AndroidX
Keep reading

Related articles