React Native Expo SDK 51 Upgrade: Starting April 24, 2025, iOS apps must be built with the iOS 18 SDK.
My Descent into the Podfile Abyss (and How I Climbed Out) Upgrading Expo SDK 50 → 51 in the Bare workflow to meet Apple’s iOS 18 SDK requirement. If you’re a React Native developer you want to stay in the sweet spot of library stability—but sometimes a looming deadline forces your hand. You start getting emails like this: App Store Connect Warning Hello, We noticed one or more issues with a recent delivery for the following app: Quiznect Version 1.0.40 Build 40 ITMS-90725: SDK version issue - This app was built with the iOS 17.5 SDK. Starting April 24, 2025, all iOS and iPadOS apps must be built with the iOS 18 SDK or later, included in Xcode 16 or later, in order to be uploaded to App Store Connect or submitted for distribution. Apple’s deadline arrived, so I had to upgrade my Expo app. I ran: npx expo upgrade …and hoped for the best. Sometimes it works flawlessly. Other times you end up on a multi‑day debugging odyssey through Podfiles, build logs, environment variables, and EAS configurations. This is the story of my upgrade from Expo SDK 50 → SDK 51 in the Bare Workflow. It wasn’t pretty, but I emerged with an iOS 18 SDK‑compliant build. May my tale of woe and triumph save you some time and sanity! ⸻ The Goal • Upgrade from Expo SDK 50 to SDK 51 • Meet Apple’s iOS 18 SDK requirement (Xcode 16+) by April 24, 2025 • Stay reasonably up‑to‑date without jumping straight to SDK 52 ⸻ Initial Steps & The First Hurdle: Dependencies & Workflow Commit all changes, then run: npx expo upgrade Expo CLI pointed out manual steps—because I use the Bare workflow (I manage ios/ & android/ in Git). Lesson 1: Know your workflow (Managed vs. Bare). The native‑dir upgrades differ significantly. I had an old patch-package workaround causing build failures on the build server. Lesson 2: Clean up obsolete workarounds & devDependencies before upgrading. ⸻ Targeting the Right SDK (and Dependencies) I first tried expo@latest (SDK 52) but pivoted to the stable SDK 51. In package.json: "dependencies": { "expo": "~51.0.0", // target SDK 51 "react": "...", "react-native": "...", // … }, Then: npx expo install --fix npm list expo react react-native expo-modules-core When mismatches persisted, I: npm cache clean --force sudo rm -rf node_modules rm package-lock.json npx expo install --fix Verified correct versions: • Expo 51.x • React 18.2.0 • RN 0.74.x • expo‑modules‑core 1.12.x Lesson 3: Manually set your SDK version in package.json • Clean‑install when deps get stuck • Always verify with npm list, don’t blindly trust --fix ⸻ The Pod Install Gauntlet cd ios npx pod-install Common Errors & Fixes uninitialized constant FlipperConfiguration - Remove or comment out old Flipper logic in ios/Podfile. cannot load such file ... native_modules - Comment out the bad require_relative in Podfile or install @react-native-community/cli. undefined method use_expo_modules! - Ensure require for expo/scripts/autolinking is present. React-Runtime Hermes → minimum deployment target; Bump platform :ios, '15.0' (RN 0.74 needs ≥ 14.0/15.0). Unable to find a specification for fmt: rm ios/Podfile.lock to clear stale lock. Unable to find a specification for ExpoModulesCore: npm uninstall expo-random → npx expo install expo-crypto npx expo install expo-modules-core pod cache clean --all + pod repo update Ensure source: 'https://cdn.cocoapods.org/' in Podfile. Lesson 4: Pod errors come in waves—fix one, the next appears. Lesson 5: Match your iOS deployment target to your RN version. Lesson 6: Deleting Podfile.lock often forces a fresh, clean resolution. Lesson 7: Migrate deprecated packages early. Lesson 8: Verify JS

My Descent into the Podfile Abyss (and How I Climbed Out) Upgrading Expo SDK 50 → 51 in the Bare workflow to meet Apple’s iOS 18 SDK requirement.
If you’re a React Native developer you want to stay in the sweet spot of library stability—but sometimes a looming deadline forces your hand. You start getting emails like this:
App Store Connect Warning
Hello,
We noticed one or more issues with a recent delivery for the following app:
Quiznect
Version 1.0.40
Build 40
ITMS-90725: SDK version issue - This app was built with the iOS 17.5 SDK. Starting April 24, 2025, all iOS and iPadOS apps must be built with the iOS 18 SDK or later, included in Xcode 16 or later, in order to be uploaded to App Store Connect or submitted for distribution.
Apple’s deadline arrived, so I had to upgrade my Expo app. I ran:
npx expo upgrade
…and hoped for the best. Sometimes it works flawlessly. Other times you end up on a multi‑day debugging odyssey through Podfiles, build logs, environment variables, and EAS configurations.
This is the story of my upgrade from Expo SDK 50 → SDK 51 in the Bare Workflow. It wasn’t pretty, but I emerged with an iOS 18 SDK‑compliant build. May my tale of woe and triumph save you some time and sanity!
⸻
The Goal
• Upgrade from Expo SDK 50 to SDK 51
• Meet Apple’s iOS 18 SDK requirement (Xcode 16+) by April 24, 2025
• Stay reasonably up‑to‑date without jumping straight to SDK 52
⸻
Initial Steps & The First Hurdle: Dependencies & Workflow
- Commit all changes, then run: npx expo upgrade
- Expo CLI pointed out manual steps—because I use the Bare workflow (I manage ios/ & android/ in Git).
Lesson 1: Know your workflow (Managed vs. Bare). The native‑dir upgrades differ significantly. I had an old patch-package workaround causing build failures on the build server.
Lesson 2: Clean up obsolete workarounds & devDependencies before upgrading.
⸻
Targeting the Right SDK (and Dependencies)
I first tried expo@latest (SDK 52) but pivoted to the stable SDK 51. In package.json:
"dependencies": {
"expo": "~51.0.0", // target SDK 51
"react": "...",
"react-native": "...",
// …
},
Then:
npx expo install --fix
npm list expo react react-native expo-modules-core
When mismatches persisted, I:
npm cache clean --force
sudo rm -rf node_modules
rm package-lock.json
npx expo install --fix
Verified correct versions:
• Expo 51.x
• React 18.2.0
• RN 0.74.x
• expo‑modules‑core 1.12.x
Lesson 3: Manually set your SDK version in package.json
• Clean‑install when deps get stuck
• Always verify with npm list, don’t blindly trust --fix
⸻
The Pod Install Gauntlet
cd ios
npx pod-install
Common Errors & Fixes
- uninitialized constant FlipperConfiguration - Remove or comment out old Flipper logic in ios/Podfile.
- cannot load such file ... native_modules - Comment out the bad require_relative in Podfile or install @react-native-community/cli.
- undefined method use_expo_modules! - Ensure require for expo/scripts/autolinking is present.
- React-Runtime Hermes → minimum deployment target; Bump platform :ios, '15.0' (RN 0.74 needs ≥ 14.0/15.0).
- Unable to find a specification for fmt: rm ios/Podfile.lock to clear stale lock.
- Unable to find a specification for ExpoModulesCore: npm uninstall expo-random → npx expo install expo-crypto npx expo install expo-modules-core pod cache clean --all + pod repo update Ensure source: 'https://cdn.cocoapods.org/' in Podfile.
Lesson 4: Pod errors come in waves—fix one, the next appears.
Lesson 5: Match your iOS deployment target to your RN version.
Lesson 6: Deleting Podfile.lock often forces a fresh, clean resolution.
Lesson 7: Migrate deprecated packages early.
Lesson 8: Verify JS