Fix: React Native Android Build Failed
Part of: JavaScript & TypeScript Errors
Quick Answer
How to fix React Native Android build failures — SDK version mismatches, Gradle errors, duplicate module issues, Metro bundler problems, and NDK configuration for common build errors.
The Error
Running npx react-native run-android or building with Gradle fails:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> error: package com.facebook.react does not existOr an SDK version error:
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':app'.
> Failed to find target with hash string 'android-34' in: /usr/local/lib/android/sdkOr a duplicate module error:
error: duplicate files copied in APK META-INF/...
File 1: /path/to/.gradle/...
File 2: /path/to/.gradle/...Or after upgrading React Native:
Invariant Violation: "main" has not been registered.
This can happen if:
* Metro (the local dev server) is run from the wrong folder.
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.Why This Happens
React Native Android builds involve multiple layers — the React Native framework, Gradle build system, Android SDK, and your JavaScript bundle — each of which can fail independently. A successful build requires exact version alignment across the entire toolchain: the Java Development Kit, the Android Gradle Plugin, the Gradle wrapper, the Android SDK platform version, and the React Native version itself. When any of these fall out of sync, the build fails with error messages that often point to the symptom rather than the root version mismatch.
The most frequent trigger is upgrading React Native without updating the surrounding toolchain. React Native 0.73 and later require Java 17, AGP 8.x, and Gradle 8.x, while older versions require Java 11 with AGP/Gradle 7.x. Mixing them produces cryptic Gradle errors that don’t mention Java at all. Similarly, native modules written in C++ depend on a specific NDK version. Installing the wrong NDK version or letting Android Studio auto-update to a newer one breaks native compilation silently.
Common causes:
- Android SDK target version not installed — the
compileSdkVersionortargetSdkVersioninbuild.gradlespecifies an SDK version that isn’t installed in your Android SDK. - Gradle wrapper version mismatch — the Gradle version in
gradle-wrapper.propertiesis incompatible with the Android Gradle Plugin (AGP) version. - Java version mismatch — React Native 0.73+ requires Java 17. Older versions may conflict with newer Java.
- Duplicate dependencies — two different packages include the same library at different versions. Gradle fails to resolve the conflict.
- Metro bundler not running —
run-androidtries to connect to Metro on port 8081, but Metro isn’t running or is running on the wrong port. - CMake/NDK issues — native modules that require C++ compilation fail if NDK or CMake isn’t installed or is the wrong version.
node_modulesout of sync — after upgrading React Native or adding packages, the native code innode_modulesdoesn’t match what was compiled.
How Other Tools Handle This
React Native CLI is not the only way to build a mobile app with JavaScript or Dart. Each alternative handles the Android build toolchain differently, and understanding those differences clarifies which problems are inherent to Android development and which are specific to React Native’s architecture.
Expo (managed workflow / dev client / EAS Build) abstracts away the entire native build. In a managed Expo project, there is no android/ directory at all. You write JavaScript, and Expo’s cloud service (EAS Build) produces the APK/AAB. SDK versions, NDK versions, and Gradle configurations are pinned internally by the Expo SDK version you choose. When you run expo start, there is no Gradle invocation on your machine. The trade-off is that you cannot use arbitrary native modules. If a library requires custom native code (JNI, custom Gradle plugins), you must “eject” to a dev client or bare workflow, at which point you face the same Gradle issues as vanilla React Native. EAS Build is still useful here because it runs the native build on a consistent CI image with known SDK/NDK versions.
Flutter also compiles to native Android code via Gradle, but Flutter controls the Gradle configuration more tightly. flutter create generates a build.gradle that pins AGP and Gradle wrapper versions compatible with the current Flutter SDK. Running flutter doctor checks the entire toolchain (Java, Android SDK, Xcode, etc.) and reports mismatches before you attempt a build. Flutter does not use a JavaScript bridge, so there is no Metro-equivalent step. Build failures in Flutter are almost always pure Gradle/Android SDK issues, not bridge or bundler problems. NDK management is simpler because Flutter’s Dart-to-native compilation uses its own engine and does not depend on the NDK for the framework itself (only for plugins with C/C++ code).
Capacitor (Ionic) takes a web app and wraps it in a native WebView container. npx cap sync copies your built web assets into the android/ project. The Gradle build itself is simpler because Capacitor does not compile JavaScript to native code. Build failures are typically limited to plugin native code or SDK version mismatches, not bundler or bridge issues. Capacitor uses a standard Android Studio project structure, so Android Studio’s built-in tooling (SDK Manager, Gradle sync) works without special configuration.
Hermes vs JSC affects build complexity within React Native itself. Hermes (the default engine since RN 0.70) compiles JavaScript to bytecode ahead of time, which adds a compilation step to the Gradle build. If the Hermes version bundled with your React Native version is incompatible with your NDK, the build fails during the Hermes compilation phase. JavaScriptCore (JSC) is the older engine and does not require ahead-of-time compilation, but it produces slower runtime performance. If you see build failures in :ReactAndroid:build related to Hermes compilation, switching to JSC temporarily (hermesEnabled: false in build.gradle) can isolate whether the issue is Hermes-specific.
React Native New Architecture (Fabric + TurboModules) changes the native build significantly. With the New Architecture enabled (newArchEnabled=true in gradle.properties), the build generates C++ binding code via Codegen, which requires CMake and a compatible NDK version. This adds a build step that does not exist in the old architecture. If you are upgrading an existing app and enable the New Architecture, expect new build failures related to Codegen output, missing CMake, or incompatible third-party libraries that have not been updated for Fabric.
Fix 1: Install the Required Android SDK Version
The error “Failed to find target with hash string ‘android-34’” means the SDK version specified in build.gradle isn’t installed:
# Check what's installed
sdkmanager --list | grep "platforms;android"
# Install the required version (e.g., android-34)
sdkmanager "platforms;android-34"
sdkmanager "build-tools;34.0.0"Or install via Android Studio:
- Open Android Studio -> SDK Manager (Tools -> SDK Manager)
- SDK Platforms tab -> check the version your project requires
- SDK Tools tab -> ensure “Android SDK Build-Tools” is installed for that version
Check which version your project needs:
// android/build.gradle
ext {
compileSdkVersion = 34 // This version must be installed
targetSdkVersion = 34
minSdkVersion = 21
buildToolsVersion = "34.0.0"
}Fix 2: Fix Gradle and Java Version Issues
React Native 0.73+ requires Java 17. Check your Java version and Gradle compatibility:
# Check Java version
java -version
# java version "17.0.x" or "11.0.x"
# Check JAVA_HOME
echo $JAVA_HOME
# Set JAVA_HOME if needed (macOS with Homebrew Java 17)
export JAVA_HOME=$(/usr/libexec/java_home -v 17)Common compatibility matrix:
| React Native | AGP | Gradle | Java |
|---|---|---|---|
| 0.76+ | 8.x | 8.6+ | 17 |
| 0.73-0.75 | 8.x | 8.x | 17 |
| 0.71-0.72 | 7.x | 7.x | 11 |
| 0.68-0.70 | 7.x | 7.x | 11 |
Update Gradle wrapper version:
# android/gradle/wrapper/gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zipUpdate Android Gradle Plugin in android/build.gradle:
buildscript {
dependencies {
classpath("com.android.tools.build:gradle:8.1.4") // Match your Gradle version
}
}Common Mistake: Multiple Java versions installed on the same machine is the single most common cause of “builds on my colleague’s machine but not mine.” Run
which javaand verify it points to the expected version. On macOS,/usr/libexec/java_home -Vlists all installed JDKs.
Fix 3: Clean Build Artifacts
Stale build cache causes many unexplained failures. Clean everything and rebuild:
# Clean React Native build
cd android
./gradlew clean
cd ..
# Clear Metro bundler cache
npx react-native start --reset-cache
# Clear watchman cache (if installed)
watchman watch-del-all
# Remove node_modules and reinstall
rm -rf node_modules
npm install
# or
yarn install
# For iOS too (if needed)
cd ios && pod install && cd ..One-liner for a full reset:
cd android && ./gradlew clean && cd .. && \
rm -rf node_modules android/.gradle && \
npm install && \
cd android && ./gradlew assembleDebugFix 4: Fix Duplicate Module/File Errors
When two dependencies include the same file, the APK packer fails:
Duplicate files copied in APK META-INF/DEPENDENCIES
File 1: ...
File 2: ...Fix in android/app/build.gradle:
android {
packagingOptions {
// Exclude duplicate meta-info files
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/*.kotlin_module'
}
}For duplicate native library (.so) files:
android {
packagingOptions {
pickFirst 'lib/x86/libc++_shared.so'
pickFirst 'lib/x86_64/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
}
}Fix 5: Fix Metro Bundler Connection Issues
run-android connects to Metro at localhost:8081 to load the JS bundle. If Metro isn’t running or the device can’t reach it:
Start Metro manually first:
# Terminal 1 — start Metro
npx react-native start
# Terminal 2 — build and run the app
npx react-native run-androidFor physical Android devices, the device needs to reach your development machine’s Metro server:
# Forward port 8081 from device to your machine
adb reverse tcp:8081 tcp:8081
# Then run the app
npx react-native run-androidCheck Metro is running:
curl http://localhost:8081/status
# Should return: {"status":"packager-status:running"}If Metro crashes or shows module errors, clear the cache:
npx react-native start --reset-cacheFix 6: Fix “has not been registered” Error
This error means the app started but the JS bundle failed to load or the component wasn’t registered:
// WRONG — component name must match exactly what's in index.js
AppRegistry.registerComponent('MyApp', () => App);
// index.js — the registered name must match the app name in app.json
AppRegistry.registerComponent(appName, () => App);// app.json
{
"name": "MyApp", // Must match the first arg of registerComponent
"displayName": "My App"
}If the bundle loads but a module fails:
# Check Metro output for the specific error
npx react-native start 2>&1 | grep -i error
# Try loading the bundle directly in a browser
curl http://localhost:8081/index.bundle?platform=androidFix 7: Fix NDK and Native Module Build Errors
If a package requires native code compilation:
Error: NDK at /path/to/sdk/ndk was not found.
No version of NDK matched the requested versionInstall NDK via Android Studio:
- SDK Manager -> SDK Tools -> NDK (Side by side) -> Install
- Note the installed version (e.g.,
25.2.9519653)
Specify NDK version in android/build.gradle:
android {
ndkVersion "25.2.9519653" // Match what you installed
}Or in android/local.properties:
ndk.dir=/path/to/sdk/ndk/25.2.9519653For CMake not found:
sdkmanager "cmake;3.22.1"Pro Tip: Pin the NDK version explicitly in your project rather than relying on whatever Android Studio installs. Different team members with different Android Studio versions will get different NDK versions, causing “works on my machine” failures. Add the
ndkVersiontobuild.gradleand document it in the project README.
Still Not Working?
Check the full Gradle error output:
cd android
./gradlew assembleDebug --stacktrace --info 2>&1 | tail -100
# --stacktrace shows the full Java stack trace
# --info shows verbose Gradle outputCheck for conflicting React Native versions:
# See what version is installed
cat node_modules/react-native/package.json | grep '"version"'
# Check for multiple React versions (should be one)
npm ls reactVerify Android SDK path:
# android/local.properties must point to your SDK
cat android/local.properties
# sdk.dir=/Users/you/Library/Android/sdk (macOS)
# sdk.dir=C\:\\Users\\you\\AppData\\Local\\Android\\Sdk (Windows)If local.properties is missing, create it or let Android Studio create it by opening the android/ folder as a project.
Run on an emulator vs physical device. Some build issues are device-specific. If a physical device fails, try an emulator, and vice versa.
Check if the New Architecture is causing failures:
# android/gradle.properties
# Temporarily disable to isolate the issue
newArchEnabled=falseIf the build succeeds with newArchEnabled=false, the failure is related to Codegen, Fabric, or TurboModules. Check that all your third-party libraries support the New Architecture before re-enabling it.
Verify the Hermes engine is not the issue:
// android/app/build.gradle
// Temporarily switch to JSC to test
project.ext.react = [
enableHermes: false
]If the build succeeds with Hermes disabled, the problem is in the Hermes compilation step. Update your NDK version or check for Hermes-specific build errors in the Gradle output.
For related React Native issues, see Fix: React Native Metro Bundler Failed, Fix: Xcode Build Failed, Fix: Expo Not Working, and Fix: Gradle Build Failed.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: React Native Metro Bundler Failed to Start or Bundle
How to fix React Native Metro bundler errors — unable to resolve module, EMFILE too many open files, port already in use, transform cache errors, and Metro failing to start on iOS or Android.
Fix: Expo Router Not Working — Routes Not Matching, Layout Nesting Wrong, or Deep Links Failing
How to fix Expo Router issues — file-based routing, layout routes, dynamic segments, tabs and stack navigation, modal routes, authentication flows, and deep linking configuration.
Fix: NativeWind Not Working — Styles Not Applying, Dark Mode Broken, or Metro Bundler Errors
How to fix NativeWind issues — Tailwind CSS for React Native setup, Metro bundler configuration, className prop, dark mode, responsive styles, and Expo integration.
Fix: React Native Paper Not Working — Theme Not Applying, Icons Missing, or Components Unstyled
How to fix React Native Paper issues — PaperProvider setup, Material Design 3 theming, custom color schemes, icon configuration, dark mode, and Expo integration.