Failed React Native migration: diagnosis and recovery plan
By Nathan Guigui, Founder of GUIGUI Tech · Facts checked against the official sources listed at the end of the article
A React Native migration that went wrong can almost always be recovered, provided you stop piling up fixes and start again in the right order: freeze the scope, secure the version in production, run a migration audit to find out exactly what is breaking, then upgrade one version step at a time, test on real devices and release progressively to the stores.
The information below is current as of October 2026.
How do you know a React Native migration has gone wrong?
A React Native migration has gone wrong when the team can no longer ship a stable version of the app on a predictable timeline. The symptoms often overlap:
- the migration branch no longer builds on iOS, Android or both, and every fix surfaces a new error;
- the app builds but crashes, sometimes only in production builds;
- two versions coexist: the old one in production, the new one never stable enough to replace it;
- a store deadline is approaching and the only version able to meet it is not ready.
The diagnosis is the same for a migration to React Native (from a native, Cordova, Ionic or web app) and for a React Native or Expo version upgrade.
What are the most common causes of a failed React Native migration?
The most common causes of a failed React Native migration are incompatible native dependencies, the New Architecture, version jumps that are too large, poorly measured performance regressions and a codebase left half-migrated. They often compound one another.
Incompatible native libraries
Navigation, maps, payments, camera: these libraries contain native code, and every version upgrade can break one of them. An abandoned library will never ship the compatible version you are waiting for. This is the most common blocker, and it is often discovered late because nobody took an inventory up front.
The New Architecture: Fabric and TurboModules
The New Architecture replaces the old "bridge" between JavaScript and native code with Fabric (rendering) and TurboModules (native modules). According to the official React Native 0.82 announcement, since October 8, 2025 it is the only architecture available: newArchEnabled=false on Android and RCT_NEW_ARCH_ENABLED=0 on iOS are ignored. The interop layers, which let many libraries written for the old architecture keep working, are being kept, but the Expo documentation points out that this compatibility is not perfect. In-house native modules written for the old bridge are a frequent source of crashes. See our article on the mandatory New Architecture.
Expo SDK jumps that are too large
Skipping several Expo SDK versions stacks up every breaking change in between. The Expo documentation recommends upgrading one version at a time, so you can pinpoint what breaks at each step.
Performance regressions
Before concluding there is a regression, check how it was measured. The React Native documentation notes that the JavaScript thread is much slower in development mode and that performance should always be tested in release builds. Regressions confirmed in release builds then need to be tracked down screen by screen.
A half-migrated codebase
Coming from a native app, React Native can be adopted gradually: the React Native documentation says it also works well for adding a single view or user flow to an existing app. That is a legitimate approach, as long as there is a plan to finish. Without one, the team maintains two stacks indefinitely and every feature costs twice as much.
Broken iOS and Android builds
CocoaPods errors, incompatible Gradle or Android Gradle Plugin versions, the wrong Xcode: fixing them one at a time, without going back to the prerequisites of the target React Native version, only drags the crisis out.
What should you do first when a React Native migration has gone off the rails?
The first thing to do is freeze the scope: no new features and no "while we're at it" dependency upgrades until the app is stable again. Then:
- Secure production. Make sure the last released version can be rebuilt and republished if an urgent fix is needed, and write down the tool versions (Node, Xcode, JDK) that make it possible.
- Freeze the migration branch. Stop the trial-and-error and document what builds, what doesn't and the errors you see.
- Check store deadlines, which determine how much room you have (see below).
Key point
If the old version of the app no longer builds either, that is the top priority: without it, you cannot ship a single fix while the migration is under way.
How do you run a React Native migration audit?
A React Native migration audit takes a complete inventory of the app before work resumes, to answer one question: what is stopping you from shipping, and in what order should it be fixed? Our diagnostic checklist:
| What to check | What we look for |
|---|---|
| Current and target versions | React Native, Expo SDK, React, gap to the target version |
| Build tooling | Node, Xcode, CocoaPods, Gradle, Android Gradle Plugin, JDK |
| Android configuration | targetSdkVersion, compliance with Google Play requirements |
| Dependencies | Maintenance status and New Architecture compatibility of each library |
| In-house native code | Native modules and components written by the team |
| Builds | Debug and release, iOS and Android, locally and in CI |
| Behavior | Critical flows, crashes, visual and performance regressions |
| History | Skipped steps, accumulated temporary fixes |
For an Expo project, npx expo-doctor checks dependencies against React Native Directory, the community library directory, as described in the Expo documentation. Without Expo, the check is done dependency by dependency.
Which recovery plan should you follow after a failed migration?
The recovery plan follows a set order: start again from a healthy base, deal with dependencies, upgrade one step at a time, test on real devices, then release progressively.
- Start from a base that works. If the migration branch is too far gone, it is often faster to start again from the stable version and redo the migration cleanly, salvaging only the useful changes. A healthy base lets you trace each error to a single cause.
- Decide on each blocking dependency: upgrade, replace, fork or rewrite. The Expo documentation suggests a dedicated branch where incompatible libraries are temporarily removed until the app runs. For a blocking third-party dependency, the React Native team recommends contacting its maintainers directly.
- Upgrade one step at a time, with a build and tests at each step:
- Expo: one SDK version at a time, then
npx expo install --fixandnpx expo-doctor, as described in the Expo documentation; - React Native without Expo: the Upgrade Helper, recommended by the React Native documentation, which shows every change between two versions, including native files you must update by hand;
- New Architecture: move to React Native 0.81 or Expo SDK 54 first, enable it there and validate the app, then upgrade to 0.82 or later, as the React Native team recommends.
- Expo: one SDK version at a time, then
- Test on real devices, in release builds: critical flows (sign-in, payment, notifications, deep links, camera) on several iPhones and Android devices, including an older one, compared against the production version.
- Release progressively, using the store tools described below.
How do you release a migrated React Native app without risking everything?
To release a migrated app without risking everything, go through the stores' testing channels (TestFlight, Play Console testing), then through a progressive release you can stop.
| Step | iOS | Android |
|---|---|---|
| Internal testing | TestFlight, up to 100 internal testers | Internal testing, up to 100 testers |
| Wider testing | TestFlight, up to 10,000 external testers (Apple review) | Closed or open testing |
| Release | 7-day phased release, can be paused | Staged rollout, can be halted |
On Google Play, according to Play Console Help, a staged rollout reaches the percentage of users you choose, which you increase yourself. Halting it stops new users from getting the version, but those who already have it keep it: a problem is fixed with a new release. Staged rollouts are only available for updates, not for a first release.
On the App Store, according to App Store Connect Help, a phased release rolls the update out over 7 days to users with automatic updates turned on, from 1% to 100%, with up to 30 days of pause in total. Anyone can still download the update manually from the App Store in the meantime. Monitor crashes at each step.
What if a Google Play or Apple deadline hits during the migration?
If a store deadline hits while a migration is stuck, first assess whether the production version can be brought into compliance on its own, without waiting for the migration to finish. As of October 2026:
- Google Play: according to Android Developers, since August 31, 2026, new apps and updates must target Android 16 (API 36), with an extension available until November 1, 2026 on request. Existing apps targeting Android 14 (API 34) or lower are no longer offered to new users on newer Android versions. More details in our article on the Google Play API 36 requirement.
- Apple: according to Apple's published requirements, since April 28, 2026, apps uploaded to App Store Connect must be built with Xcode 26 or later.
An old React Native version may not build with these tools; compliance then requires a minimum version upgrade. And according to the React Native release policy, only the latest three minor series are maintained: the gap only keeps growing.
When should you stop a React Native migration and rethink it?
You should stop and rethink a React Native migration when finishing it costs more than another approach, based on a costed inventory. The signals:
- most of the code will have to be rewritten anyway (in-house native modules, abandoned libraries with no replacement);
- the version upgrade has turned into a rewrite without anyone deciding so;
- two stacks coexist with no end date;
- the target was the wrong one: a mostly web app moved to React Native when a hybrid approach would have been enough. For a Cordova or Ionic app, the Capacitor documentation explains that Capacitor can run alongside Cordova, which makes for a lighter migration.
Rethinking does not mean throwing everything away: narrowing the scope to critical flows, changing the technical target or restarting from a healthy base are all options. In our experience, the worst option is to carry on without deciding, adding fixes to a branch nobody knows how to stabilize anymore.
If the migration is part of a wider project that went wrong, our guide Failed app rebuild: what to do now? covers recovering your access and choosing between saving and rebuilding.
Getting help from GUIGUI Tech
GUIGUI Tech offers a React Native Migration Audit at €1,500 excl. VAT, delivered in 5 business days: analysis of the code, dependencies and blockers, a costed and prioritized migration plan, a report and a debrief call. If you then hire us for the full migration or the Expo / New Architecture upgrade, the audit is deducted from the final price, provided you confirm within 30 days. If the problem goes beyond the migration (developer gone, lost access, an app unstable across the board), the App Rescue Audit, at the same price, starts by recovering your access and decides between saving, partly rebuilding or starting over.
Depending on what the migration audit finds, recovery can take the form of a Full React Native Migration, from €18,000 excl. VAT over 4 to 8 weeks, an Expo SDK & New Architecture Upgrade, from €6,500 excl. VAT over 2 to 4 weeks, or a Cordova / Ionic to Capacitor Migration, from €9,500 excl. VAT over 3 to 6 weeks. Nathan Guigui, the studio's founder, has been working with React Native for ten years.
Frequently asked questions
What should you do when a React Native migration has failed?
Why is a React Native upgrade stuck?
Can you skip several React Native or Expo versions at once?
What is a React Native migration audit?
How do you release a migrated React Native app safely?
When should you abandon a React Native migration and change course?
Need help with this?
React Native Migration Audit
Running a React Native app in production on an old version? We analyze it and hand you a costed, prioritized migration plan.
Learn more →
Sources
- Upgrading to new versions (official React Native documentation)
- React Native Upgrade Helper (React Native Community)
- Releases: version support policy (official React Native documentation)
- React Native 0.82 - A New Era, announcement of October 8, 2025 (official React Native blog)
- Performance overview (official React Native documentation)
- Integration with existing apps (official React Native documentation)
- Upgrading Expo SDK walkthrough (Expo documentation)
- Using React Native’s New Architecture (Expo documentation)
- Migrating from Cordova to Capacitor (Capacitor documentation)
- Target API level requirements for Google Play (Android Developers)
- Release app updates with staged rollouts (Play Console Help)
- Set up an open, closed, or internal test (Play Console Help)
- Release a version update in phases, App Store Connect Help (Apple Developer)
- TestFlight (Apple Developer)
- Upcoming requirements for App Store Connect (Apple Developer)
