Diagnosing Expo SDK upgrade crashes from native modules and EAS channels
Diagnose launch crashes after `npx expo upgrade` by matching native module SDK versions and EAS Update channels before rebuilding.
14 Aug 2026, 08:54 UTC

Problem and takeaway
After running `npx expo upgrade`, your app crashes immediately on launch with errors such as `Module X is not registered` or `Class not found`. The useful takeaway is that the crash usually comes from one of two mismatches: native code compiled for an older Expo SDK, or an EAS Update channel serving a bundle built for a different SDK than the installed client. This guide helps you identify which mismatch is present and apply the matching fix.
A development client is a custom build of your app that can load different Expo updates without rebuilding native code. An EAS Update channel is a named stream of updates that clients subscribe to based on the channel value in your app configuration. A native module is library code that runs in iOS or Android native code rather than JavaScript.
Recognizable condition and likely causes
Look for this combination after an SDK upgrade:
- The app was working before `npx expo upgrade`.
- The crash happens during launch, before the JavaScript bundle renders.
- Error messages mention native modules, missing classes, or unknown modules.
| Observed failure | Likely cause | Where to confirm |
|---|---|---|
| Launch crash with `Module X is not registered` or `Class not found` | Third-party native module compiled against an older Expo SDK and missing `expo-module-build-plugin` configuration or native `mods` required by the newer SDK | `package.json`, library documentation, `ios/Podfile.lock`, `android/app/build.gradle` |
| Runtime API mismatch after an update loads | EAS Update channel serves a bundle built for SDK N while the installed client runs SDK N+1 | `eas.json`, `app.config.js` or `app.json`, EAS dashboard channel history |
The term mods refers to Expo config plugin hooks that modify native project files during `npx expo prebuild`.
Ordered diagnostic checks
Run `npx expo doctor`
Run this in the project root. It requires no special permissions and is read-only. Review the output for critical dependency mismatches involving `expo`, `expo-updates`, and third-party libraries. Expected check: no critical mismatches for the target SDK. Risk: none; this command only inspects the project.
Inspect dependency versions
Open `package.json`, `ios/Podfile.lock`, and `android/app/build.gradle`. Confirm that `expo` and `expo-updates` match the SDK you upgraded to, and that each library with native code lists compatibility with that SDK. Expected check: version numbers align with the Expo compatibility matrix for the target SDK. Risk: none; file inspection only.
Check library configuration
For any library reporting a native error, check whether its README or plugin configuration requires `expo-module-build-plugin` or a specific `mods` entry. Missing configuration often means the native code was not regenerated for the new SDK. Expected check: library docs show a supported version for your SDK. Risk: none.
Compare EAS Update channels
Open `eas.json` and `app.config.js` (or `app.json`). Note the `update.channel` value and any build profile channels. Then check the EAS dashboard for the bundle SDK version associated with that channel. Expected check: the channel serves a bundle built for the same SDK as the installed client. Risk: none; reading configuration only.
Reproduce in a development client
Before applying fixes, build a development client with `eas build --profile development`, install it on a device or emulator, and confirm the launch crash. This requires an Expo account and network access. Expected check: the crash reproduces consistently so you can verify the fix later. Risk: build commands change remote build state but do not alter your local source.
Fixes tied to findings
If the cause is an incompatible native module
- Upgrade the library to a version that supports your target SDK. Check the library's compatibility matrix or release notes.
- If the library uses config plugins, confirm `expo-module-build-plugin` is declared in `app.config.js` if required by the library.
- Run `npx expo prebuild --clean` in the project root. This regenerates the `ios/` and `android/` directories from scratch. Required permissions: write access to the project directory. Expected checks: command completes without errors; `ios/Podfile.lock` and `android/app/build.gradle` reflect updated dependencies. Risk: this command deletes and regenerates native directories, so any manual native changes not captured by config plugins will be lost.
- Rebuild the development client with `eas build --profile development` and install it.
- Launch the app and confirm the crash no longer occurs.
If the cause is an EAS Update channel mismatch
- Create a dedicated channel for the target SDK, for example `production-sdk-<TARGET_SDK>`, instead of reusing a channel that previously served an older SDK.
- Update `eas.json` and `app.config.js` so builds and updates point to the matching channel:
// eas.json example (replace <TARGET_SDK> with your actual SDK version)
{
"build": {
"development": {
"channel": "development-sdk-<TARGET_SDK>"
}
},
"update": {
"channel": "production-sdk-<TARGET_SDK>"
}
}
// app.config.js example
export default {
expo: {
updates: {
channel: "production-sdk-<TARGET_SDK>",
},
},
};
- Publish the update to the dedicated channel using `eas update --branch <CHANNEL_NAME>`. Required permissions: EAS account with update access. Expected check: EAS dashboard shows the new bundle associated with the channel and SDK version. Risk: publishing to the wrong channel can deliver an incompatible bundle to existing clients.
- Load the update in the development client and confirm the runtime API mismatch disappears.
Limitations
- `npx expo prebuild` cannot perform manual native changes in bare workflow projects; those require editing native files directly.
- Expo SDK versions and EAS Update behavior change frequently. Verify commands and version assumptions against the current SDK documentation before applying fixes.
- Do not reuse the same EAS channel across SDK major versions without testing staging builds first.
- This draft requires current verification against the latest Expo SDK documentation before being applied in production.
Practical verification
- Run `npx expo doctor` and confirm it reports no critical dependency mismatches for the target SDK.
- Build a development client with `eas build --profile development`, install it, and confirm the app launches without the original crash.
- Publish an update to a dedicated EAS channel and load it in the development client to confirm channel and SDK compatibility.
Rollback
Because `npx expo prebuild --clean` regenerates native directories, it changes local state. Before running it, commit all changes in Git or back up `ios/` and `android/`. To roll back, revert the Git commit, restore the backed-up native directories, and run `cd ios && pod install` if you are using CocoaPods. Then rebuild the development client to return to the previous working state.
Escalation criteria
Escalate to the library maintainer or Expo forums if:
- The crash persists after a clean `prebuild`, dependency upgrade, and fresh development client build.
- The library has no release that supports your target SDK.
- The channel mismatch continues after publishing to a dedicated SDK channel.
Include `npx expo doctor` output, your SDK versions, and a minimal reproduction when you escalate.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.