An EAS Build Android "failed to assemble" error means the Gradle step that assembles your app crashed, and the real cause is in the Gradle log, not in that summary line. The three most common causes are an OutOfMemoryError from too little build memory, a Gradle or Android Gradle Plugin version mismatch, and incompatible or broken node modules. Open the Run gradlew phase of the build log, find the actual error, and fix that: raise the build memory with a larger resource class, align your versions with expo doctor, or repair dependencies with expo install. Do not guess from the summary alone.
Short answer
"Failed to assemble" is the generic result of a failed Gradle assemble step, so the first move is to read the Gradle log and find the specific error. Per the Expo EAS Build troubleshooting guide, most failures fall into memory, version, and dependency problems. An OutOfMemoryError means the build needs more memory, which you get by using a larger resource class and raising Gradle's heap. A Gradle, plugin, or Kotlin version conflict means aligning versions, which expo doctor helps with. Broken node modules mean reinstalling and running expo install to fix compatible versions. Fix the exact error the log names rather than the summary.
What "failed to assemble" means
The message comes from the Gradle command EAS runs to build your Android app, which assembles or bundles the release. When that command exits with an error, EAS reports that the build failed to assemble, but that phrase is just the outcome; it does not say why. The why is always in the detailed log for the gradlew step.
This matters because the same summary can hide very different problems. A memory crash, a dependency that will not resolve, and a version conflict all end in a failed assemble, and each needs a different fix. Treat "failed to assemble" as a prompt to open the log, not as a diagnosis in itself.
Read the Gradle log first
Before changing anything, open the build on the Expo dashboard and expand the Run gradlew phase, which contains the actual Gradle output. Scroll to the first real error rather than the last line, since Gradle often prints a cascade of follow-on failures after the original one. The first error message, and the module or dependency it names, is what you act on.
Reading the log saves you from fixing the wrong thing. An OutOfMemoryError, a Could not resolve message, a Duplicate class error, and an autolinking failure look nothing alike in the log even though they share the same summary. Identify which one you have, and the correct fix usually follows directly from the error text. Copying the exact error line into a search, alongside your Expo SDK version, is often the fastest way to find whether it is a known issue with a documented fix.
OutOfMemoryError: give the build more memory
If the log shows an OutOfMemoryError or a Java heap space error, the build ran out of memory while assembling, which is common for larger React Native apps with many native modules. The direct fix is to give the build more memory by selecting a larger resource class in eas.json for the Android build profile, which provisions a machine with more RAM.
Alongside the machine size, raise Gradle's own heap limit. Setting a higher value such as a four gigabyte maximum in the org.gradle.jvmargs property in android/gradle.properties lets Gradle use the extra memory the larger resource class provides. Using both together, a bigger machine and a higher Gradle heap, resolves the majority of memory-related assemble failures.
Gradle and plugin version mismatches
If the log shows a version conflict, an unsupported Gradle feature, or a message that a plugin requires a newer Gradle, the cause is a mismatch between your Gradle wrapper, the Android Gradle Plugin, Kotlin, and what a dependency expects. This often appears after adding a library that needs a newer toolchain than your project is set up for.
The reliable fix is to align versions rather than bump one in isolation. Running expo doctor flags dependencies that do not match your Expo SDK, and letting Expo manage the Gradle, plugin, and compile-SDK versions for your SDK release keeps them consistent. If you have custom native configuration, make sure it targets versions compatible with your Expo SDK rather than the newest available.
Node modules and dependency issues
If the failure points to autolinking, a missing native module, or a dependency that will not resolve, the problem is usually in your node modules. A native module version that does not match your React Native or Expo version, or a duplicated dependency, can break the assemble step before any memory or Gradle issue is reached.
Start by running expo install to align native dependencies to versions compatible with your SDK, which fixes the most common mismatch. If problems persist, remove node_modules and the lockfile, reinstall cleanly, and check for two versions of the same native library being pulled in. A clean, compatible dependency tree removes a large share of assemble failures that are not about memory.
Common causes at a glance
Most assemble failures map to a short list. The table below links the error you see in the log to its likely cause and the direction of the fix.
| Error in the log | Likely cause | Fix direction |
|---|---|---|
| OutOfMemoryError or Java heap space | Not enough build memory | Larger resource class, raise Gradle heap |
| Could not resolve or version conflict | Gradle, plugin, or Kotlin mismatch | Align versions with expo doctor |
| Duplicate class | Conflicting or duplicated dependencies | Deduplicate, exclude a transitive copy |
| Autolinking or missing native module | Incompatible module version | Run expo install, reinstall cleanly |
| Config or prebuild error | App config or native setup issue | Fix the config, regenerate prebuild |
Use the table to translate the log into a plan. Once you know which row you are in, the fix is specific, and you avoid the common mistake of raising memory for a problem that is actually a version conflict.
Fix checklist
Work the problem in order rather than trying everything at once. The checklist below moves from reading the log to reproducing the build.
| Check | Action | Done? |
|---|---|---|
| Read the log | Find the first real Gradle error, not the summary | [ ] |
| Memory | Set a larger resource class and raise the Gradle heap | [ ] |
| Versions | Run expo doctor and align Gradle and plugin versions | [ ] |
| Dependencies | Run expo install, then reinstall node_modules cleanly | [ ] |
| Reproduce | Try a local build to iterate faster than cloud builds | [ ] |
The step that saves the most time is reproducing the build locally once you have a hypothesis, since a local run gives you a much faster feedback loop than waiting on cloud builds. Change one thing at a time so you know which fix actually resolved the assemble failure.
After it builds: scan the artifact
Getting the build to assemble is about the toolchain, not about whether the resulting app is safe to ship. Once your .aab or .apk builds, it can still contain security issues that have nothing to do with Gradle, such as over-broad permissions, cleartext traffic, or a secret embedded during development.
A scanner like PTKD.com analyzes your app build and reports findings ordered by severity and mapped to OWASP MASVS, so you catch those before release. To be clear about the boundary: PTKD does not fix a Gradle error, add build memory, or resolve a dependency conflict. It checks the successfully built artifact for the security and privacy issues that a green build does not rule out.
What to take away
- "Failed to assemble" is a generic Gradle failure; the real cause is the first error in the Run gradlew log, not the summary.
- An OutOfMemoryError means give the build more memory with a larger resource class and a higher Gradle heap.
- A version conflict means aligning Gradle, plugin, and Kotlin versions, which expo doctor helps you do for your Expo SDK.
- Autolinking and unresolved dependency errors usually mean running expo install and reinstalling node_modules cleanly.
- After the build succeeds, scan the artifact with PTKD.com for the security issues a green build does not catch.




