We use the flavors into our apps to use different version. We have dev, test and prod. When we have upgraded to 0.63, to classpath("com.android.tools.build:gradle:3.5.3") and distributionUrl=https://services.gradle.org/distributions/gradle-6.2-all.zip, we cannot use the appbundle.
when we run ./gradlew bundleDevRelease -> we cannot find into the app-dev-release.aab the index.android.bundle. This cause a crash when open the app.
If we run this command : ./gradlew bundleRelease -> it build all variants
app-dev-release.aab -> missing
app-test-release.aab -> index.android.bundle present
app-prod-release.aab -> index.android.bundle present
it seems that the first time not set the index.android.bundle into assets
System:
OS: macOS 10.15.2
CPU: (4) x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
Memory: 382.96 MB / 16.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 11.10.0 - /usr/local/bin/node
Yarn: 1.13.0 - /usr/local/bin/yarn
npm: 6.7.0 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.9.2 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
Android SDK:
API Levels: 23, 27, 28, 29
Build Tools: 26.0.2, 27.0.3, 28.0.3, 29.0.2
System Images: android-19 | Google APIs Intel x86 Atom, android-23 | Google APIs Intel x86 Atom_64, android-27 | Intel x86 Atom_64, android-28 | Google APIs Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: 4.0 AI-193.6911.18.40.6514223
Xcode: 11.3/11C29 - /usr/bin/xcodebuild
Languages:
Java: 1.8.0_201 - /usr/bin/javac
Python: 2.7.16 - /usr/bin/python
npmPackages:
@react-native-community/cli: Not Found
react: 16.13.1 => 16.13.1
react-native: 0.63.0 => 0.63.0
npmGlobalPackages:
react-native: Not Found
1.Create a new project: npx react-native init AppName --template react-native-template-typescript
Obtain an .aab file into android/build/outputs/bundle/devRelease. when i open the .aab i expect to find the folder base and into the base the folder assets that contain the index.android.bundle.
One more clue here, I find that we have to run ./gradlew bundleRelease twice as "index.android.bundle" will be missing in the first generated AAB. After running the same command again, this time "index.android.bundle" will be included in the final AAB.
Thanks for the issue @lorenzoangelini!
One more clue here, I find that we have to run
./gradlew bundleReleasetwice as "index.android.bundle" will be missing in the first generated AAB. After running the same command again, this time "index.android.bundle" will be included in the final AAB.
Hmm are you saying after the second run of ./gradlew bundleRelease it is generated correctly?
In a sense, yes. Below is what I have in my release script for Android side. It works well so far.
./gradlew clean
./gradlew bundleRelease; ./gradlew bundleRelease # Fix bug, index.android.bundle is not included in AAB
fastlane android upload
Otherwise, "index.android.bundle" won't be included in the generated AAB. I saw that "index.android.bundle" generation step is invoked but it is simply not included in AAB.
@safaiyeh @thanakij yes it seems that the first time the folder assets with "index.android.bundle" is not present.
Run twice the ./gradlew bundleRelease for me is not a just solution, because the build time is x2.
In my case if i run bundleRelease i get three apps, dev,test and production. Where in dev, it crash when launch the app, because is missing the "index.android.bundle".
The goal is launch for example ./gradlew bundleRelease and obtain the an aab that works, like the previous version of the gradle. I think that is a problem of cli.
I use a monorepo.
I would like to provide my setting below:
react-native: 0.62.2
Gradle: 6.4.1
Gradle Plugin: 4.0.1
proguard: enabled
Hopefully, this would help maintainers fix the issue.
With this i have the issue:
react-native: 0.63.2
com.android.tools.build:gradle:3.5.3
https://services.gradle.org/distributions/gradle-6.2-all.zip
With this version the issue is not present
react-native: 0.63.2
com.android.tools.build:gradle:3.4.2
https://services.gradle.org/distributions/gradle-5.5-all.zip
I have a build with the same problem. The bundle is missing but the images are copied correctly it seems.
Can anyone confirm their images are also present in the drawable folders?
I can confirm that running a double-build (ie. ./gradlew bundleRelease twice) solves the issue. Not obviously a good long term solution, but definitely a hint to what's going on.
react-native: 0.63.2
com.android.tools.build:gradle:3.5.3
@thanakij with the same gradle configuration and with
def enableProguardInReleaseBuilds = false
the index.android.js is correctly injected in the aab archive without the need to run a double-build.
I haven't reproduce the same behaviour with a new react-native project.
I think that the main problem is when there are multiple dex files as in my project.
The same issue happened to me when com.android.tools.build:gradle: was updated to 3.5.3 => 4.1.0 and
https://services.gradle.org/distributions/gradle to 5.5 => 6.5
Seeing from reports from others looks like the issue is related to Gradle
Running assembleXX twice did resolve the issue locally
I'm running into this as well. In my case I'm attempting to assembleRelease instead of bundleRelease.
Everything is correct in the APK (all assets present) except it's missing the bundle! The bundle gets generated without issue, it's sitting in the correct directory, it just never gets added to the APK for unknown reasons. I've been tearing my hair out all day trying to figure out how/why this is happening.
Unfortunately running assembleRelease twice does not solve the problem.
It's definitely caused by the upgrade to android gradle plugin 4.1. Reverting to 3.6.4 fixes the issue however I need to use 4.1 for other reasons.
@safaiyeh Did you ever get to take a look at this? I think it can be reproduced on any app with multidex by upgrading gradle to 6.5+ and android gradle plugin to 4.1.0+. Do a clean and then assembleRelease and the APK will contain everything except the app bundle which remains in the generated outputs.
I have a reproducible project here => https://github.com/tomoima525/android_build_test_rn
@tomoima525 thanks, I'll look into it in next few days
I'm running into this as well. In my case I'm attempting to
assembleReleaseinstead ofbundleRelease.Everything is correct in the APK (all assets present) except it's missing the bundle! The bundle gets generated without issue, it's sitting in the correct directory, it just never gets added to the APK for unknown reasons. I've been tearing my hair out all day trying to figure out how/why this is happening.
Unfortunately running
assembleReleasetwice does not solve the problem.It's definitely caused by the upgrade to android gradle plugin 4.1. Reverting to 3.6.4 fixes the issue however I need to use 4.1 for other reasons.
@safaiyeh Did you ever get to take a look at this? I think it can be reproduced on any app with multidex by upgrading gradle to 6.5+ and android gradle plugin to 4.1.0+. Do a clean and then
assembleReleaseand the APK will contain everything except the app bundle which remains in the generated outputs.
Are you running clean before running assembleRelease the second time? If you run clean then the asset bundle file gets removed so it will not be included in the apk/aab file
@tomoima525 @dulmandakh I found a workaround. It seems to be a gradle task ordering issue. It appears that assets get merged before the bundle gets copied to the intermediate output directory. Adding the following to android/app/build.gradle forces the bundle copy task to happen before merging assets.
//Fix for bundle not getting included in APK or AAB with android gradle plugin 4+
//Seems like there's a task ordering issue and the assets get computed before the bundle is copied
//This forces the copy task to run before merge resources
project.afterEvaluate {
tasks.findAll { task ->
task.name.startsWith('merge') && task.name.endsWith('Resources')
}.each { t -> t.dependsOn "copyReleaseBundledJs" }
}
I have little knowledge of gradle so this isn't a great workaround, it doesn't account for different build variants etc but at least it works for basic :app:assembleRelease. I guess gradle or android plugin behavior changed at some point that causes this task ordering issue to crop up. I don't know enough about gradle to track down the actual source but hopefully this gives more knowledgeable people a good clue to go on =)
@AndrewMorsillo Amazing, thank you for your input! Your idea does make sense and solves the issue. I dug into react.gradle and just gave a patch. The issue seems resolved by testing it on my reproducible repository.
@tomoima525 @AndrewMorsillo In my case with Proguard enabled doesn't work. The intermediates/merged_asset is generated beforegenerated/assets.
@alessioemireni interesting. I'll check with my reproducible repository https://github.com/tomoima525/android_build_test_rn in my spare time( I turned off proguard in that project because assembleRelease failed with OOM). Can you also check the behavior with the fix I made in #30177 ?
@tomoima525 yes, I have applied a patch with your fix, but the result is the same.
react-native: 0.62.2
gradle-tool: 6.0.1
gradle-plugin: 3.6.4
I have also increased the gradle plugin version to 4.1+ but the bundle is missing in aab.
@alessioemireni your case seems something different. This is reproducible when android gradle plugin is 4.1 and gradle is 6.5.
In fact the issue did not happen with android gradle plugin 3.5.3/ gradle 6.2 on my environment somehow. (which strangely contradict with the original issue, but if you create an app with create-react-native-app it will come with plugin 3.5.3/ gradle 6.2 but the issue is not reproducible)
@dulmandakh
I have the reproducible case and fixed case with the fix I made in https://github.com/facebook/react-native/pull/30177.
Do you mind reviewing & checking it?
Repository: https://github.com/tomoima525/android_build_test_rn
To reproduce the issue, run the command below
$ cd android
$ ./gradlew clean :app:assembleRelease // or ./gradlew clean :app:releaseBundle
app-release.apk will be generated but it does not have index.android.bundle build
I added the fix in https://github.com/facebook/react-native/pull/30177 . Running the command below will apply the patch to react.gradle and you can see the issue is resolved
$ yarn add_patch
$ cd android
$ ./gradlew clean :app:assembleRelease // or ./gradlew clean :app:releaseBundle
index.android.bundle is generated under assets

(The script is tested on Mac. If the copying does not work on Linux, try directly copying the react-patch.gradle to node_modules/react-native/react.gradle)
Huge thanks to @tomoima525 and @AndrewMorsillo for all of your work finding a solution!
I was having a nearly identical issue where doing ./gradlew clean assembleProductionRelease would result in this error: java.lang.RuntimeException: Unable to load script. Make sure you're either running a Metro server (run 'react-native start') or that your bundle 'index.android.bundle' is packaged correctly for release. but ONLY when you did a clean. Running the same command again as ./gradlew assembleProductionRelease would work.
For people who don't want to manually patch the node_modules/react-native/react.gradle until React Native does the next release, I've hacked together a solution (based on the work of @tomoima525 and @AndrewMorsillo) that you can drop into your app/build.gradle at the top level:
// This forces the copy task to run before merge resources. This should be removable starting with RN 0.63.4.
project.afterEvaluate {
def isAndroidLibrary = plugins.hasPlugin("com.android.library")
def variants = isAndroidLibrary ? android.libraryVariants : android.applicationVariants
variants.all { def variant ->
def targetName = variant.name.capitalize()
def mergeResourcesTask = tasks.findByName("merge${targetName}Resources")
def assetsCopyTask = tasks.findByName("copy${targetName}BundledJs")
mergeResourcesTask.dependsOn(assetsCopyTask)
logger.warn("Making task ${mergeResourcesTask} depend on ${assetsCopyTask}")
}
}
Sorry to comment on this issue again. But the patch by @plowman works only for assemble builds not but bundling aab unfortunately.
Huge thanks to @tomoima525 and @AndrewMorsillo for all of your work finding a solution!
I was having a nearly identical issue where doing
./gradlew clean assembleProductionReleasewould result in this error:java.lang.RuntimeException: Unable to load script. Make sure you're either running a Metro server (run 'react-native start') or that your bundle 'index.android.bundle' is packaged correctly for release.but ONLY when you did a clean. Running the same command again as./gradlew assembleProductionReleasewould work.For people who don't want to manually patch the
node_modules/react-native/react.gradleuntil React Native does the next release, I've hacked together a solution (based on the work of @tomoima525 and @AndrewMorsillo) that you can drop into yourapp/build.gradleat the top level:// This forces the copy task to run before merge resources. This should be removable starting with RN 0.63.4. project.afterEvaluate { def isAndroidLibrary = plugins.hasPlugin("com.android.library") def variants = isAndroidLibrary ? android.libraryVariants : android.applicationVariants variants.all { def variant -> def targetName = variant.name.capitalize() def mergeResourcesTask = tasks.findByName("merge${targetName}Resources") def assetsCopyTask = tasks.findByName("copy${targetName}BundledJs") mergeResourcesTask.dependsOn(assetsCopyTask) logger.warn("Making task ${mergeResourcesTask} depend on ${assetsCopyTask}") } }
In my project assetsCopyTask is null
Sorry to comment on this issue again. But the patch by @plowman works only for assemble builds not but bundling aab unfortunately.
@nilavassg what command are you running and what error are you seeing?
In my project assetsCopyTask is null
@FelipeLimaDeSouza you can add a line so that mergeResourcesTask.dependsOn(assetsCopyTask) is only called if both mergeResourcesTask and assetsCopyTask are not null.
Sorry to comment on this issue again. But the patch by @plowman works only for assemble builds not but bundling aab unfortunately.
@nilavassg what command are you running and what error are you seeing?
In my project assetsCopyTask is null
@FelipeLimaDeSouza you can add a line so that
mergeResourcesTask.dependsOn(assetsCopyTask)is only called if both mergeResourcesTask and assetsCopyTask are not null.
I did this but it comes null in all commands.
I did this but it comes null in all commands.
@FelipeLimaDeSouza I see. I'm not an expert at any of this. My only guess is that tasks.findByName("copy${targetName}BundledJs") and tasks.findByName("merge${targetName}Resources") can't find the proper tasks in your environment. Perhaps because the targetName in these cases has different capitalization than what we're expecting? Idk.
If you do this you can find the steps which should be candidates:
# Starting at your root project directory
cd ./android
./gradlew tasks --all | grep -E "^app:merge.+Resources"
# For comparison, here is my output:
# app:mergeInternalDebugAndroidTestResources
# app:mergeInternalDebugResources
# app:mergeInternalReleaseResources
# app:mergeProductionDebugAndroidTestResources
# app:mergeProductionDebugResources
# app:mergeProductionReleaseResources
./gradlew tasks --all | grep -E "^app:copy.+BundledJs"
# For comparison, here is my output:
# app:copyInternalDebugBundledJs - copy bundled JS into InternalDebug.
# app:copyInternalReleaseBundledJs - copy bundled JS into InternalRelease.
# app:copyProductionDebugBundledJs - copy bundled JS into ProductionDebug.
# app:copyProductionReleaseBundledJs - copy bundled JS into ProductionRelease.
I did this but it comes null in all commands.
@FelipeLimaDeSouza I see. I'm not an expert at any of this. My only guess is that
tasks.findByName("copy${targetName}BundledJs")andtasks.findByName("merge${targetName}Resources")can't find the proper tasks in your environment. Perhaps because thetargetNamein these cases has different capitalization than what we're expecting? Idk.If you do this you can find the steps which should be candidates:
# Starting at your root project directory cd ./android ./gradlew tasks --all | grep -E "^app:merge.+Resources" # For comparison, here is my output: # app:mergeInternalDebugAndroidTestResources # app:mergeInternalDebugResources # app:mergeInternalReleaseResources # app:mergeProductionDebugAndroidTestResources # app:mergeProductionDebugResources # app:mergeProductionReleaseResources ./gradlew tasks --all | grep -E "^app:copy.+BundledJs" # For comparison, here is my output: # app:copyInternalDebugBundledJs - copy bundled JS into InternalDebug. # app:copyInternalReleaseBundledJs - copy bundled JS into InternalRelease. # app:copyProductionDebugBundledJs - copy bundled JS into ProductionDebug. # app:copyProductionReleaseBundledJs - copy bundled JS into ProductionRelease.
Even with the task in the task list, it returns null.
I had to run the "bunbleRelease" command twice to work.
Sorry to comment on this issue again. But the patch by @plowman works only for assemble builds not but bundling aab unfortunately.
Me too, the solution from @tomoima525 only solves some part of the problem. It is still not working in case of AAB.
I have gone through _react.gradle_ file and investigated the output when running bundleRelease. The remaining issue is because the task copyReleaseBundleJs is executed before bundleReleaseJsAndAssets. In short, the copy task is executed before the actual JS generation task.
Below line will make it works with "bundleRelease" (in addition to "assembleRelease"):
currentAssetsCopyTask.dependsOn(currentBundleTask)
Sorry to comment on this issue again. But the patch by @plowman works only for assemble builds not but bundling aab unfortunately.
@nilavassg what command are you running and what error are you seeing?
./gradlew bundleProdRelease
Also confirmed the same by @thanakij
Desculpe comentar sobre este assunto novamente. Mas o patch de @plowman funciona apenas para builds de montagem, n茫o, mas para empacotar aab, infelizmente.
Eu tamb茅m, a solu莽茫o de @ tomoima525 resolve apenas parte do problema. Ainda n茫o est谩 funcionando no caso de AAB.
Eu _examinei o_ arquivo _react.gradle_ e investiguei a sa铆da ao executar bundleRelease . O problema restante 茅 porque a tarefa copyReleaseBundleJs 茅 executada antes de bundleReleaseJsAndAssets . Resumindo, a tarefa de c贸pia 茅 executada antes da tarefa real de gera莽茫o de JS.
A linha abaixo far谩 com que funcione com "bundleRelease" (al茅m de "assembleRelease"):
currentAssetsCopyTask.dependsOn(currentBundleTask)
Did you change for that?
currentAssetsCopyTask.dependsOn(currentBundleTask)
def mergeResourcesTask = tasks.findByName("merge${targetName}Resources")
mergeResourcesTask.dependsOn(currentAssetsCopyTask)
Below is what I have:

Below is what I have:
Worked for me. Thank you
@thanakij This works!馃敟. Thank you.
Most helpful comment
Huge thanks to @tomoima525 and @AndrewMorsillo for all of your work finding a solution!
I was having a nearly identical issue where doing
./gradlew clean assembleProductionReleasewould result in this error:java.lang.RuntimeException: Unable to load script. Make sure you're either running a Metro server (run 'react-native start') or that your bundle 'index.android.bundle' is packaged correctly for release.but ONLY when you did a clean. Running the same command again as./gradlew assembleProductionReleasewould work.For people who don't want to manually patch the
node_modules/react-native/react.gradleuntil React Native does the next release, I've hacked together a solution (based on the work of @tomoima525 and @AndrewMorsillo) that you can drop into yourapp/build.gradleat the top level: