“Gradle task assembleRelease failed with exit code 1” — The Flutter Triage Guide
Gradle task assembleRelease failed with exit code 1 is not an error message — it is the envelopean error arrives in. Exit code 1 is Gradle's generic failure status; the actual cause is printed earlier in the log, and there are dozens of distinct possibilities that all end in this identical line. We run a build pipeline that has classified hundreds of failed Flutter builds into ~40 named causes, so instead of guessing, this page gives you the two-step method to find your real error, then the causes ranked by how often they actually occur.
Step 1: read the right part of the log
The information is above the exit line. Scroll up and find the first error:, FAILURE: Build failed with an exception, or What went wrong: block — cascading failures print multiple errors and the earliest one is almost always the true cause. Two flags help when the output is thin: flutter build apk --release --verbose and Gradle's --stacktrace.
Then read the task name in the failure line — it names the stage and the module:
:app:compileFlutterBuildRelease → your Dart code doesn't compile. :app:checkReleaseAarMetadata → a dependency demands a newer compileSdk (full guide). :some_plugin:compileReleaseKotlin → a plugin module is the casualty, usually a version mismatch. :app:validateSigningRelease → signing config points at a keystore that isn't there.
Step 2: match against the ranked causes
Ranked by real frequency across the classified Flutter/Android failures on our pipeline — not by guesswork:
1. Your source doesn't compile (~1 in 5 classified failures)
The biggest class by a wide margin: Dart or Kotlin errors in the project itself — syntax errors, APIs removed by newer package versions, null-safety violations. The log shows file and line. There is no toolchain fix for this one; the compiler is right. If the errors reference package APIs that changed, pinning the package to the version your code was written against is the fast path.
2. Dependency conflicts and dead packages
The second-largest family: two plugins demanding incompatible versions of the same library, a package yanked from pub.dev, or a plugin built against a Flutter API that no longer exists. The log names the packages. flutter pub deps shows the resolution; dependency_overrides is the blunt instrument that usually works. The classic instance — intl pinned at ^0.19 fighting flutter_localizations — is common enough that our pipeline rewrites it automatically.
3. The removed Flutter v1 embedding (old projects)
Projects generated years ago reference Android embedding v1, which current Flutter removed. The telltale is io.flutter.app.FlutterApplication in the manifest or errors about the deleted embedding classes. The real fix is migrating the android/ folder — or building the project against a Flutter version from its own era, which is why we keep era-matched toolchain images (3.19 / 3.24 / current) and select automatically from the project's own signals.
4. compileSdk / AAR-metadata walls
A dependency compiled against a newer Android API than your project's compileSdk — the “compile against version 36 or later” message. One line to fix in the simple case, messier when a plugin pins its own compileSdk; the dedicated guide covers both, including the subprojects override.
5. Broken project structure and signing configs
Uploads missing the Gradle wrapper, an android/ folder without a manifest, a build.gradle referencing my-upload-key.jks that only exists on the original author's laptop. The signing case is especially common in purchased templates and hand-me-down projects: delete or guard the signingConfigs block, or let a managed key sign it.
6. Toolchain disagreements (Gradle × JDK × AGP)
“Builds on my machine, fails on yours” is almost always this: an old Gradle that cannot run on a new JDK, or an AGP below what a dependency requires. The error names the versions. These are mechanical to fix (wrapper bump, AGP bump) and mechanical to automate — our pipeline's floor-raising repairs exist because this family kept recurring across unrelated projects.
When the log genuinely says nothing
A minority of failures print the exit line with no usable error above it — the process died, the daemon vanished, memory ran out. Honest advice: this is where local debugging stops being worth it. Re-run once (daemon crashes are flaky), check RAM if you're in CI, and if it persists, put the project through a pipeline that instruments the build: upload the project and a failed build comes back with the classified cause — which dependency, which version, what to change — instead of the wrapper line, with the credit refunded on failure. The auto-repairs (wrapper regeneration, AGP/Kotlin/compileSdk floors, desugaring) fire before you ever see those classes as failures at all. For the broader guide to building APKs without a local Android setup, start at Flutter APK builds online.
Code2Native Engineering
Engineering team
Written by the Code2Native engineering team — the people who build and operate the cloud build pipeline.