Updating standalone always use old JS bundle at first launch

Updating standalone always use old JS bundle at first. Happens on both iOS and Android. Tested with TestFlight and Google Play Beta.

  1. For example, 1.0.0 is based on SDK v25 while 2.0.0 is based on SDK v27.
  2. Install the old version and open. => 1.0.0.
  3. Update app on testflight and open. => Still 1.0.0
    4, Close app and open it again. => 2.0.0

Related issue before: Standalone iOS app update doesn't immediately update js

I am surprised that not many people has reported this issue before. I have seen it from SDK v1x until now, and it is actually quite a serious issue.

Causing another bug for SDK v27

Even more serious now is that my new app based on SDK v27.0.0 is unable to use the location service after upgrading the standalone. But it works fine if I uninstall it and install a brand new one.

I suspect it is due to it loading the old js bundle (which is confirmed happening) for v25 in the new SDK v27 build and crashes something that cannot be reverted. No matter the cause of this, fixing the above issue should fixes this also.

Because of this, I am holding back my SDK v27 deployment after having gone through so much pain on waiting and fixing everything. Because my current user’s app will crash after updating.


re: code updating. you can actually configure the behavior of code updating now.
@esamelson wrote up a summary of the new stuff here:

i think what you want is to set the timeout for a synchronous update to something higher than 0.

Maybe set updates.fallbackToCacheTimeout to something like 10000 in your app.json.

re: the location problem. a few days ago, we had a bug where location stuff was broken for SDK27. If you build a new app using the build service from scratch, it should be resolved now. very sorry for that trouble. let us know if rebuilding your production app doesn’t solve that problem.

Hi @ccheever, thanks for the reply.

  1. My updates in app.json:
"updates": {
      "enabled": true,
      "checkAutomatically": "ON_ERROR_RECOVERY"

fallbackToCache should be talking about Automatic Updates, but I have already implemented my own manual update in background. So it is not needed.

This problem (using old bundle) is not starting from sdk v27, but long long time ago. I am expecting that when a user update his app from appstore and then open it, it should be using the js bundle within the new standalone, instead of the old/cached one

  1. I have built again after seeing another reply from you, but still the same.

The whole Location package failed. The reproduction procedure is as follow:

  1. Install app of SDK v25 version
  2. Open it once and allow the permission
  3. Update it
  4. Open it and askAsync seems to be denied or undetermined (cannot confirm this in standalone, but at least I know its not grantes because of some custome logics of my own).
  5. Close app and reopen, still the same
  6. Uninstall and reinstall.
  7. Works perfectly.

My guess is: the permission granted in app based on SDK v25 is not carried onto app based on SDK v27 crashes something permanantly. And will never recover even after closing the app.

Note: These might be 2 independent issues.



  1. Open app v25 and do not grant location permission (meaning no accept nor reject)
  2. Update app v27 and open
  3. WORK perfectly

re: the location thing. We just deployed another fix related to permissions. Maybe try another build? Sorry you are having trouble.

I’ll ask someone else on the team about the code updating thing.


Thanks a lot. The location permission is working now when updating old build to the new one.

But the JS version is still the old one on the first launch (only), so the first issue is still not fixed.

Hi @carsonwah, regarding the old JS version, when you perform a standalone build, we embed the most recent publication you have for the project. You can view the most recent publication by running something like exp publish:history --platform ios in your project directory. Could you try publishing a more recent version of your project, then performing a build to see if that fixes things?

more info here:

Hi @quinlanj, thanks for the reply.

I understand the workflow of publishing and building, but the updated standalones just use the old JS (instead of the embedded JS) for the first launch. Newly installed standalones works perfectly.

Publish history

Here is my result from exp publish:history --platform ios:

Reproducing issue

For example, I have two builds:

SDK version Build version Embedded JS version
v25.0.0 1.3.9 1.3.9
v27.0.0 1.4.5 1.4.5

Then, do the followings:

  1. Install v1.3.9 in TestFlight
  2. Open it, showing version 1.3.9
  3. Update to app with build version 1.4.5 in TestFlight
  4. Open it, still showing version 1.3.9
    • (which is not even in the same channel, of the same SDK version)
  5. Close app, reopen, showing version 1.4.5
    • (not downloaded remotely because I have set "checkAutomatically": "ON_ERROR_RECOVERY")

Btw, this happens on ios AND android.

Build procedure

I am building a standalone each time with following precedures:

# Publish updates
exp publish --release-channel prod-v4

# Build apps
exp build:ios --release-channel prod-v4 --no-publish  # --no-publish will use the most recent published release
exp build:android --release-channel prod-v4  --no-publish

Investigation direction

Can you guys have a check on the logics of choosing js version in standalones?

The updated standalone may be using the JS cache in local storage, but using embedded JS should be prior to using the JS cache.

1 Like

hi @carsonwah, thank you for your detailed report, it really helped in figuring out what exactly the problem was. I’ve gone ahead and made a github issue to track this – https://github.com/expo/expo/issues/1719 .

@quinlanj Thanks a lot! Really hope Expo gets better and better. Just @ me if I could provide any help on this.

1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.