EAS build app crashes just on production but works fine when using dev-client [iOS]

I’m on managed workflow, SDK 44. My app works fine when I’m testing it by expo-dev-client. But when I try to test with a production build, in an iOS simulator, it crashes. I tried sending it to App Store but they rejected it because of the same reason. I did set up Sentry, and the only error that it gives me is “OutOfMemory”, something related to RAM. The production build works fine on Android.

My package.json:

{

  "scripts": {

    "start": "expo start",

    "android": "expo start --android",

    "ios": "expo start --ios",

    "web": "expo start --web",

    "eject": "expo eject"

  },

  "dependencies": {

    "@expo-google-fonts/poppins": "^0.2.0",

    "@firebase/firestore-types": "^2.3.0",

    "@react-native-async-storage/async-storage": "~1.15.0",

    "@react-native-community/masked-view": "0.1.10",

    "@react-native-community/slider": "4.1.12",

    "@react-native-google-signin/google-signin": "^7.0.1",

    "@react-navigation/bottom-tabs": "^5.11.11",

    "@react-navigation/native": "^5.9.4",

    "@react-navigation/stack": "^5.14.5",

    "@sentry/react-native": "^3.1.1",

    "axios": "^0.21.1",

    "expo": "^44.0.0",

    "expo-app-loading": "~1.3.0",

    "expo-apple-authentication": "~4.1.0",

    "expo-application": "~4.0.1",

    "expo-auth-session": "~3.5.0",

    "expo-av": "~10.2.0",

    "expo-constants": "~13.0.0",

    "expo-crypto": "~10.1.1",

    "expo-dev-client": "~0.8.0",

    "expo-device": "~4.1.0",

    "expo-file-system": "~13.1.0",

    "expo-firebase-recaptcha": "~2.1.0",

    "expo-font": "~10.0.4",

    "expo-notifications": "~0.14.0",

    "expo-random": "~12.1.1",

    "expo-screen-orientation": "~4.1.1",

    "expo-status-bar": "~1.2.0",

    "expo-updates": "~0.11.4",

    "firebase": "8.2.3",

    "formik": "^2.2.9",

    "lodash": "^4.17.21",

    "react": "17.0.1",

    "react-dom": "17.0.1",

    "react-native": "0.64.3",

    "react-native-autoheight-webview": "^1.5.8",

    "react-native-calendars": "^1.1266.0",

    "react-native-gesture-handler": "~2.1.0",

    "react-native-masked-text": "^1.13.0",

    "react-native-progress": "^5.0.0",

    "react-native-purchases": "^4.3.1",

    "react-native-reanimated": "~2.3.1",

    "react-native-safe-area-context": "3.3.2",

    "react-native-screens": "~3.10.1",

    "react-native-svg": "12.1.1",

    "react-native-svg-transformer": "^0.14.3",

    "react-native-web": "0.17.1",

    "react-native-webview": "11.15.0",

    "react-native-youtube": "^2.0.2",

    "react-native-youtube-iframe": "^2.2.1",

    "rn-pdf-reader-js": "^4.1.1",

    "sentry-expo": "^4.0.0",

    "styled-components": "^5.3.0",

    "yup": "^0.32.9"

  },

  "devDependencies": {

    "@babel/core": "^7.12.9",

    "@types/react": "~17.0.21",

    "@types/react-native": "~0.64.12",

    "@types/react-native-calendars": "^1.1264.2",

    "@types/styled-components": "^5.1.10",

    "@types/styled-components-react-native": "^5.1.1",

    "@typescript-eslint/eslint-plugin": "^4.28.0",

    "@typescript-eslint/parser": "^4.28.0",

    "babel-plugin-module-resolver": "^4.1.0",

    "eslint": "^7.29.0",

    "eslint-config-prettier": "^8.3.0",

    "eslint-config-prettier-standard": "^4.0.1",

    "eslint-config-standard": "^16.0.3",

    "eslint-plugin-import": "^2.23.4",

    "eslint-plugin-node": "^11.1.0",

    "eslint-plugin-prettier": "^3.4.0",

    "eslint-plugin-promise": "^5.1.0",

    "eslint-plugin-react": "^7.24.0",

    "prettier": "2.3.2",

    "prettier-config-standard": "^4.0.0",

    "tsconfig-paths": "^3.10.1",

    "typescript": "~4.3.5"

  },

  "private": true

}

I had this issue, and came to suspect that something about expo-av was causing it. I drew this conclusion by removing all suspect packages (anything installed since the last known-good build) including expo-av. Then verified that the built app not longer crashed, and then one by one added packages back until it crashed again. It took quite some time, waiting for the build each time. expo-av was the one where it crashed again…

The project is also in a monorepo and our UI library is a separate package from the native app package. The ui library package has expo-av installed as a dep, and the native package imports a component from the ui package which in turn uses expo-av. I suspected that expo install was not properly used to install expo-av to the ui library package and/or something about our monorepo setup made it too easy for a dev to install a version of expo-av that was not compatible with our version of Expo SDK (44).

The fact that ours was a monorepo will not apply to everyone, but the incompatible version may be more universal.

My solution was:

  1. Upgrade to Expo SDK 45 using expo upgrade. In the process, this ensures that other packages are installed at expo-compatible versions.
  2. Add expo version 44 as a dependency to the ui library package, and then upgrade that to 45 using expo upgrade, again insuring that other packages are expo-compatible.

And violà - 45 minutes of building, uploading, and processing later, it no longer crashes!

Lesson learned: I’ll be setting up EAS build in our CI so that I won’t have to do 10 rebuilds just to find the culprit package in the future…

Hope this helps!

10-29 06:36:40.335 11368 11368 E AndroidRuntime: FATAL EXCEPTION: main
10-29 06:36:40.335 11368 11368 E AndroidRuntime: Process: tv.dibi, PID: 11368
10-29 06:36:40.335 11368 11368 E AndroidRuntime: java.lang.AssertionError: The embedded manifest is invalid or could not be read. Make sure you have configured expo-updates correctly in android/app/build.gradle. app.manifest
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at expo.modules.updates.manifest.EmbeddedManifest.get(EmbeddedManifest.kt:31)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at expo.modules.updates.loader.LoaderTask.launchFallbackUpdateFromDisk(LoaderTask.kt:238)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at expo.modules.updates.loader.LoaderTask.start(LoaderTask.kt:99)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at expo.modules.updates.UpdatesController.start(UpdatesController.kt:290)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at expo.modules.updates.UpdatesController$Companion.initialize(UpdatesController.kt:464)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at expo.modules.updates.UpdatesPackage$createReactNativeHostHandlers$handler$1.onWillCreateReactInstanceManager(UpdatesPackage.kt:41)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at expo.modules.ReactNativeHostWrapper.createReactInstanceManager(ReactNativeHostWrapper.kt:28)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at com.facebook.react.ReactNativeHost.getReactInstanceManager(ReactNativeHost.java:39)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at tv.dibi.MainApplication.onCreate(MainApplication.java:63)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1182)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6460)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at android.app.ActivityThread.access$1300(ActivityThread.java:219)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1859)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:107)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at android.os.Looper.loop(Looper.java:214)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7356)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
10-29 06:36:40.335 11368 11368 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)