Runtime version mismatch in EAS Update native builds
0 reputation · 31 Jul 2020, 20:18 UTC
0 reputation · 31 Jul 2020, 20:18 UTC
When utilizing Expo Application Services (EAS) Update for over-the-air (OTA) deployments, the runtimeVersion defined in app.json serves as the primary guardrail. This mechanism ensures that JavaScript bundles are only delivered to clients with a compatible native binary.
A critical constraint exists where OTA updates cannot modify native code or plugins. If a deployment is pushed to a channel with a runtime version that does not align with the installed native build on the device, the application may fail to load the update or crash due to missing native dependencies.
Given the polling mechanism of the expo-updates library, there is uncertainty regarding the behavior when a client is mid-transition between two different runtime versions during a staged rollout.
34775 reputation · 01 Aug 2020, 07:23 UTC
1. Does the client prioritize the locally cached bundle over a remote manifest if the runtime version is flagged as incompatible?
Yes. When expo-updates fetches a manifest, it first checks the runtimeVersion field. If the runtime version in the manifest does not match the one embedded in the native binary, the library rejects the manifest and falls back to whatever JavaScript bundle is already cached locally. The app will not attempt to download or execute the incompatible bundle.
2. What is the specific failure state when a manifest is retrieved but the native runtime cannot support the required JS bundle version?
The app displays a red “Runtime version mismatch” screen and then crashes or becomes unresponsive. Internally, the expo-modules-core runtime throws an error during initialization because the JavaScript bundle references a module API that the native layer does not expose. The error is logged to the console and, on iOS, appears in Xcode’s console; on Android it shows in Logcat.
When a project’s package.json contains a newer or older version of expo-modules-core than the one that the EAS build process compiles into the native binary, the JavaScript runtime will expect a different major version of the module API. OTA updates cannot change native code, so if the manifest’s runtimeVersion references that newer API, the app will refuse to load it.
expo-modules-core version resolves the error.eas build --clear-cache forces a rebuild that pulls in the updated dependency.expo-modules-core that the native code was compiled against.expo-modules-core version
npm ls expo-modules-core
Check that this matches the version reported in the EAS build logs.
npx expo install expo-modules-core@<matching‑sdk‑version>
Replace <matching‑sdk‑version> with the SDK‑specific major version (e.g., 48.0.0).
eas build --clear-cache --platform all
This forces the native binary to compile with the updated expo-modules-core.
eas update --branch production --message "Align runtimeVersion"
Push the update to the same channel used by the devices.
expo diagnostics
Confirm that the resolved expo-modules-core version matches the binary and that the app starts without a mismatch error.
runtimeVersion in app.json identical across all OTA channels?expo-modules-core version?Providing the exact runtimeVersion value used in app.json and the expo-modules-core version reported by expo diagnostics will help narrow down the remaining mismatch.
Use comments to ask for clarification. Post a solution as an answer.
6,260 reputation · 31 Jul 2020, 23:32 UTC
During a staged rollout, the expo-updates library evaluates each manifest independently as it is polled. If the manifest’s runtimeVersion does not match the native binary, the manifest is discarded and treated as unavailable; no exception is thrown to the JavaScript thread unless a developer has attached an UpdateError listener. The app simply continues to run the most recently successful cached bundle (or the bundle bundled into the native binary if no cache exists). This means the client does not crash or show a red screen automatically—it only surfaces the mismatch through the error event, allowing you to handle it gracefully (e.g., prompt a full store update).