React Native

React Native Build Failing After Upgrading Expo SDK

A build that fails right after upgrading the Expo SDK almost always comes down to a dependency version mismatch — either a package that hasn't caught up to the new SDK yet, or a leftover cached build artifact from the previous SDK version that's no longer compatible.

The Problem

After running the Expo SDK upgrade and updating your project, builds start failing with errors that weren't present before:

Error: Cannot find module 'expo-modules-core'
CocoaPods could not find compatible versions for pod...
Invariant Violation: Native module cannot be null

The exact error varies depending on what specifically broke, but the common thread is that everything worked fine before the SDK upgrade.

Why It Happens

Expo SDK versions bundle specific, tested versions of React Native and core dependencies together, and moving to a new SDK version shifts what every dependency in your project is expected to be compatible with. Common causes:

  • Third-party packages in your project were built against the previous SDK's React Native version and haven't been updated to support the new one, causing native module resolution failures
  • The upgrade process updated package.json but didn't fully clear out old, incompatible native build artifacts (iOS Pods, Android Gradle caches) left over from the previous SDK version
  • Native code was manually modified in the ios/ or android/ directories (if using a bare or prebuild workflow), and those manual changes conflict with what the new SDK version expects to generate
  • Expo Go on your testing device is running an older version that doesn't support the new SDK, producing confusing errors that look like a build failure but are actually a compatibility mismatch between your project and the testing client

The Fix

First, run Expo's own doctor command, which specifically checks for exactly this category of issue:

npx expo-doctor

This surfaces dependency version mismatches directly, often naming the specific package that needs updating rather than leaving you to guess from a cryptic build error.

Use Expo's install command instead of a plain npm install for Expo-managed dependencies, since it automatically resolves versions compatible with your current SDK rather than just grabbing the latest published version of each package:

npx expo install --fix

Clear all native build caches, which is a very common missing step after an SDK upgrade. For iOS:

cd ios
rm -rf Pods Podfile.lock
pod install
cd ..

For Android:

cd android
./gradlew clean
cd ..

Clear Metro's bundler cache as well, since stale cached bundles can reference module paths or versions that no longer exist after the upgrade:

npx expo start --clear

If you're using a prebuild workflow with a checked-in ios/ or android/ directory, regenerate them cleanly rather than trying to manually reconcile differences, since the new SDK version likely changes what these native projects should look like:

npx expo prebuild --clean

This deletes and regenerates the native directories from your app config, discarding any manual native code changes — if you have custom native modifications, make sure they're captured in a config plugin or documented separately before running this, since it will remove uncommitted manual edits.

Confirm the Expo Go app (or your development build) on your test device or simulator matches the new SDK version — Expo Go versions are tied to specific SDK ranges, and an outdated Expo Go client simply can't run a project built against a newer SDK.

Still Not Working?

If a specific third-party native module is the blocker and hasn't published a compatible update yet, check its GitHub issues for an in-progress fix or a community-maintained fork that's already been updated for the new SDK — this is common enough with popular but slower-maintained packages that it's often faster than trying to patch the module yourself. As a last resort, temporarily pinning the SDK upgrade until the dependency catches up is a reasonable trade-off if the package is critical and no immediate alternative exists.