Start Debugging

Fix: Gradle task assembleDebug failed with exit code 1 in a Flutter Android build

That line is a wrapper, not the error. Re-run with flutter run --verbose or ./gradlew assembleDebug --stacktrace, read the real Gradle failure, then fix that.

The fix in one breath: Gradle task assembleDebug failed with exit code 1 is not an error, it is Flutter reporting that Gradle exited non-zero. The real failure is printed above it and is almost always truncated out of the console. Re-run with flutter run --verbose, or drop into android/ and run ./gradlew assembleDebug --stacktrace, and fix whatever Gradle actually says under * What went wrong:. In July 2026 the single most common answer is Android Gradle Plugin 9’s built-in Kotlin colliding with the legacy kotlin-android plugin, which shows up as Cannot add extension with name 'kotlin'.

FAILURE: Build failed with an exception.

BUILD FAILED in 47s
Running Gradle task 'assembleDebug'...                             48.2s
Error: Gradle task assembleDebug failed with exit code 1

This guide is written against Flutter 3.44.7 and Dart 3.12.2, the stable channel as of 2026-07-20, with notes on Android Gradle Plugin (AGP) 8.x and 9.x, Gradle 8.13, and JDK 17 and 21. The diagnosis procedure has not changed in years; the ranked causes below have, and the top one is new as of the AGP 9 rollout.

Why the message tells you nothing

assembleDebug is an Android Gradle task. The Flutter tool shells out to the Gradle wrapper in your project’s android/ directory, streams the output, and then checks the exit code. If the code is non-zero, the tool raises exactly one line: the task name and the exit code. It has no idea what went wrong, because Gradle failures are not typed, they are text.

Two things then conspire against you:

  1. The Flutter tool filters Gradle’s output. It hides the noisy configuration-phase chatter so a normal build looks clean, and in doing so it sometimes drops the block you need.
  2. Gradle itself truncates. Without --stacktrace, a Caused by: chain three levels deep gets summarized to a single line that may not name the offending plugin.

So the first move is never to guess. It is to make the build print the truth.

Get the real error before you change anything

Run these in order and stop at the first one that gives you a * What went wrong: block naming a task and a cause:

# Flutter 3.44.7, Dart 3.12.2
flutter run --verbose

If that is still opaque, bypass the Flutter tool entirely and talk to Gradle directly. This is the step most people skip, and it is the one that works:

# From the Flutter project root. Use gradlew.bat on Windows.
cd android
./gradlew assembleDebug --stacktrace --info

Gradle now prints the full failure with the module that produced it:

* What went wrong:
A problem occurred configuring project ':file_picker'.
> Failed to apply plugin 'kotlin-android'.
   > Cannot add extension with name 'kotlin', as there is an extension
     already registered with that name.

That is a real, fixable error. Gradle task assembleDebug failed with exit code 1 never was.

One more diagnostic worth running before you touch a single Gradle file, because it catches an entire class of cause on its own:

# Validates the Java, Gradle, and AGP versions against each other
flutter analyze --suggestions

The Android Java Gradle migration guide documents this validator: it evaluates your JDK, Gradle wrapper, and AGP versions as a triple and tells you which one is out of range.

Cause 1: AGP 9 built-in Kotlin versus the kotlin-android plugin

This is the dominant cause in 2026 and it is the one people misdiagnose most, because it fires during Gradle’s configuration phase, before a single line of Dart or Kotlin is compiled.

AGP 9.0 ships built-in Kotlin support and registers a Gradle extension named kotlin automatically. Any module that still applies the legacy Kotlin Gradle Plugin (kotlin-android, also known as KGP) tries to register a second extension under the same name, and Gradle refuses:

Cannot add extension with name 'kotlin', as there is an extension
already registered with that name.

The module named in A problem occurred configuring project ':x' tells you whether the offender is your own app or a package you depend on. If it is a plugin package such as file_picker or wakelock_plus, you cannot fix it in your own build files; you upgrade the package or you turn built-in Kotlin off.

The escape hatch, per the built-in Kotlin migration guide for app developers, goes in android/gradle.properties:

# android/gradle.properties -- Flutter 3.44, AGP 9.x
android.newDsl=false
android.builtInKotlin=false

That restores the pre-AGP-9 behaviour for the whole build, and Flutter’s temporary KGP shim keeps the legacy plugin working. It buys you time; it is not the destination. Flutter has filed the removal of KGP support and the removal of the old AGP DSL for a future release.

The actual migration, once every plugin you depend on supports AGP 9, is to delete the plugin and the kotlinOptions block from android/app/build.gradle.kts:

// android/app/build.gradle.kts -- AGP 9.0+, Flutter 3.47+
plugins {
    id("com.android.application")
    // id("kotlin-android")  <-- delete this line
}

android {
    // kotlinOptions { jvmTarget = JavaVersion.VERSION_17.toString() }  <-- delete this block
}

kotlin {
    compilerOptions {
        jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
    }
}

Then flip the flag:

# android/gradle.properties
android.builtInKotlin=true

Note the version floors. Flutter 3.44 raised the minimum supported KGP to 2.0.0, and the docs state that enabling built-in Kotlin requires Flutter 3.47 or later. On 3.44 stable, the correct move is android.builtInKotlin=false plus a package upgrade, not a half-finished migration. If your build instead complains that the Kotlin plugin itself is too old, that is a different failure with a different fix, covered in the Kotlin Gradle plugin version error.

Cause 2: your JDK and your Gradle wrapper disagree

The signature is a class file major version number:

Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
...
Unsupported class file major version 65

Major version 61 is Java 17, 65 is Java 21. The number tells you which JDK is running the build; the failure tells you your Gradle wrapper is too old to understand bytecode from it. Gradle releases before 7.3 cannot run under Java 17 at all, and each Gradle release has its own ceiling for the newest JDK it accepts.

This bites hardest when you did not change anything: Android Studio updated, its bundled JDK moved from 17 to 21, and your five-year-old Gradle wrapper broke overnight.

Check which JDK Flutter is using:

flutter doctor -v

Then either move the wrapper up:

# From android/. Pick the version flutter analyze --suggestions recommends.
./gradlew wrapper --gradle-version=8.13

Or pin Flutter to a JDK the wrapper can handle:

# macOS example. /usr/libexec/java_home -V lists installed JDKs.
flutter config --jdk-dir=/opt/homebrew/Cellar/openjdk@17/17.0.13/libexec/openjdk.jdk/Contents/Home

Prefer moving Gradle forward. Pinning an old JDK is a decision you will pay for again at the next AGP bump.

Cause 3: NDK version mismatch across plugins

Any package with native code declares an NDK version. If two of them disagree with what your app configured, the build stops:

* What went wrong:
Execution failed for task ':app:configureCMakeDebug[arm64-v8a]'.
> [CXX1101] NDK at .../ndk/26.3.11579264 did not have a source.properties file

Or, more explicitly:

Your project is configured with Android NDK 26.3.11579264, but the following
plugin(s) depend on a different Android NDK version:
- path_provider_android requires Android NDK 27.0.12077973

NDK releases are backward compatible, so the fix is to adopt the highest version any dependency asks for:

// android/app/build.gradle.kts -- Flutter 3.44
android {
    ndkVersion = "27.0.12077973"
}

If the error mentions a missing source.properties, the named NDK directory exists but is a partial download. Delete that directory under your Android SDK’s ndk/ folder and reinstall the version through the SDK Manager, then flutter clean.

Cause 4: a plugin raises minSdkVersion above yours

Manifest merging happens inside assembleDebug, so an SDK-level conflict surfaces as the same generic wrapper:

* What went wrong:
Execution failed for task ':app:processDebugMainManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 21 cannot be smaller than
  version 23 declared in library [:some_plugin]

Raise the floor rather than suppressing the merge with tools:overrideLibrary, which only moves the crash to runtime on the devices you excluded:

// android/app/build.gradle.kts
android {
    defaultConfig {
        minSdk = 23
    }
}

The same shape of failure with a concrete package is walked through in the write-up on background_fetch requiring minSdkVersion 21. If instead the merger complains about duplicate support-library classes, you are looking at a different problem entirely: see the AndroidX conflict during a Flutter Android build.

Cause 5: an unmaintained plugin has no namespace

AGP 8.0 made the namespace property mandatory and stopped reading package from AndroidManifest.xml. A package that has not shipped since AGP 7 fails configuration:

* What went wrong:
A problem occurred configuring project ':some_old_plugin'.
> Namespace not specified. Specify a namespace in the module's build file.

There is no supported way to inject a namespace into someone else’s package from your app. In order of preference: upgrade the package, replace it, or fork it and add namespace 'com.example.some_old_plugin' to its android/build.gradle. Scripts that rewrite files under ~/.pub-cache circulate widely for this error and they are a trap: the cache is regenerated, so the fix vanishes on the next machine and on CI.

Cause 6: nothing is wrong except the state on disk

Not every exit code 1 is a configuration problem. A half-written artifact in build/, a Gradle daemon holding a stale classpath, or a .dart_tool directory from a different SDK version all produce failures that look structural and are not. Before a long debugging session, clear the cheap ones:

flutter clean
cd android && ./gradlew --stop && ./gradlew clean && cd ..
flutter pub get
flutter run

If it builds after that, you had a stale-state problem and there is nothing further to fix. If a pub get fails on the way through, the constraint solver output is its own diagnosis exercise, covered in reading a version solving failed error in pubspec.yaml.

Variants that land on this page by mistake

The general lesson holds beyond this one message. Any time a Flutter build failure names a Gradle task and an exit code, the tool is a messenger. Go to android/, run the task yourself with --stacktrace, and read the block under * What went wrong:. The fix is always in that block, and it is never in the line Flutter printed.

Sources

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Back