A new hire clones your bare React Native 0.87 app and pod install fails on day one; how do you find which toolchain check broke?
answer
- work in dependency order
- npm install before the Podfile
- Node inside the engine range
- Gemfile CocoaPods via bundle exec
- Xcode at least 16.1, selected
basics
~20 sWalk the chain pod install depends on: JavaScript packages installed, Node inside React Native's engine range, the Gemfile's CocoaPods run through Bundler, and a full Xcode of at least 16.1 selected. The first failing link's error message names it.
solid answer
~40 sI read the first real error and check the toolchain in dependency order. The Podfile loads React Native's CocoaPods scripts from `node_modules`, so `npm install` must have run, with a Node inside 0.87's engine range (`^22.13.0 || ^24.3.0 || >= 26.0.0`). Then CocoaPods itself: `bundle install` and `bundle exec pod install`, so the Gemfile's pinned version runs instead of a random global one. Next Xcode: `use_react_native!` stops with "React Native requires XCode >= 16.1" on an older Xcode, and `xcodebuild` must point at a full Xcode, not only the Command Line Tools. Finally machine state: a committed `.xcode.env.local` or a stale spec repo. Then I write the fixes into the README or a setup script so the next hire does not hit them.
code
bash · 6 linesnode --version # inside ^22.13.0 || ^24.3.0 || >= 26.0.0
npm ci # node_modules first
xcodebuild -version # full Xcode, >= 16.1
cd ios
bundle install
bundle exec pod installgo deeper
Recall the day-one order: install JS packages, check Node, run bundle install and bundle exec pod install inside ios, and confirm Xcode is new enough.
Explain why pod install depends on node_modules, which React Native helper enforces the Xcode minimum, and what the Gemfile pin prevents.
Diagnose from the first real error, separate machine state from repo state, and turn the fix into a script and CI check.
Own onboarding cost: pinned toolchain versions, a reproducible setup path and when a dev-container or managed build service is worth adopting.
## Why pod install fails on a fresh machine `pod install` in a bare React Native app is not a self-contained step. It sits on top of four toolchains, and it fails at the **first** one that is missing or mismatched: 1. the **JavaScript dependencies** in `node_modules`, because the Podfile calls React Native's Ruby helpers that live there; 2. **Node**, because those helpers and Codegen invoke it; 3. **Ruby, Bundler and CocoaPods**, which run the Podfile; 4. **Xcode**, which React Native checks and whose tools CocoaPods uses. The fastest diagnosis walks that chain in order and reads the first genuine error rather than the last line of output. ## The checks, in order | Step | What to verify | Typical symptom | |---|---|---| | JS packages | `npm install` (or Yarn/pnpm) ran at the repo root | Podfile cannot load React Native's scripts from `node_modules` | | Node | version inside `^22.13.0 \|\| ^24.3.0 \|\| >= 26.0.0` for 0.87 | engine warnings, tooling errors, Codegen failures | | CocoaPods | `bundle install`, then `bundle exec pod install` | a different CocoaPods version than the team's, odd lock diffs | | Xcode | at least 16.1, full Xcode selected | "React Native requires XCode >= 16.1. Found …" | | Machine state | no committed `.xcode.env.local`, fresh pod specs | wrong Node path, "could not find compatible versions" | ### 1. JavaScript dependencies first The React Native Podfile calls `prepare_react_native_project!`, `use_native_modules!` and `use_react_native!`, defined in `node_modules/react-native/scripts/`. On a fresh clone without `node_modules` there is nothing to load. The fix is simply to install packages first, with the **lock file the repo uses**, so the same React Native version and native libraries are resolved. ### 2. Node inside the engine range React Native 0.87.1 declares `"node": "^22.13.0 || ^24.3.0 || >= 26.0.0"` in its `package.json`. A laptop with an older Node from a previous project is common. A `.nvmrc` or an `engines` entry at the app root, plus a version manager, makes the expected version explicit. ### 3. CocoaPods through Bundler The template's `Gemfile` pins CocoaPods (in 0.87 `~> 1.13`, excluding `1.15.0` and `1.15.1`) and a few gems newer Ruby versions no longer bundle. Running a globally installed `pod` skips those pins. The docs' fallback is exactly: - `cd ios` - `bundle install` - `bundle exec pod install` ### 4. Xcode version and selection Inside `use_react_native!`, React Native reads `xcodebuild -version` and raises if it is below its minimum, printing "React Native requires XCode >= 16.1. Found X" and "Please upgrade XCode". Two variants of the same failure: - **Xcode too old**: upgrade it; separately, React Native's minimum iOS deployment target is **15.1**. - **Only Command Line Tools selected**: `xcodebuild` cannot report an Xcode version, so the check only warns about an unexpected version string and the missing Xcode tooling surfaces as later failures. Select the full Xcode, as the setup guide describes under Xcode's Locations settings. ### 5. Machine-specific leftovers - A **committed `ios/.xcode.env.local`** carries someone else's absolute Node path; it belongs in `.gitignore`, as the template has it. - A **stale local CocoaPods spec repository** can make a newly pinned pod version unresolvable; updating the specs during install fixes it. ## Making it not happen again The senior part of the answer is prevention. Fix the environment once, then encode it: - a setup section or script that installs JS packages, then runs `bundle install` and `bundle exec pod install`; - a pinned Node version file and the React Native minimums (Node range, Xcode 16.1) written down; - `Podfile.lock` and the `Gemfile.lock` committed so resolution is reproducible; - CI that runs the same commands on a clean machine, so a broken setup is noticed before the next hire. ## Reading the output well `pod install` output is long, and the root cause is rarely the last line. Scroll up to the **first** error or raised exception: a Ruby `LoadError` or missing-file error points at `node_modules`; a React Native message about the Xcode version points at Xcode; a resolution message from CocoaPods about incompatible versions points at the lock file, the spec repository or a library's podspec. Warnings printed before the failure, such as an unexpected Xcode version string, are often the real clue. Asking the new hire for the full log, not a screenshot of the tail, saves most of the time.
- In React Native 0.87, what exactly happens when pod install runs with Xcode 15?`use_react_native!` calls React Native's minimum-Xcode check, which parses `xcodebuild -version`, prints "React Native requires XCode >= 16.1. Found 15.x" and raises "Please upgrade XCode", so the install stops before any pods are resolved.
- Why does the order npm install, then pod install matter in a bare React Native app?The Podfile's React Native helpers and the autolinking step read from `node_modules`: the CocoaPods scripts live in `react-native/scripts`, and the native libraries to link are found among installed packages. Without the JS install, the Podfile has nothing to load or link.
- How would you stop this recurring for every new hire?Encode the setup: a pinned Node version file, a script that installs packages then runs `bundle install` and `bundle exec pod install`, committed `Podfile.lock` and `Gemfile.lock`, the Xcode minimum in the README, and a CI job that runs the same steps on a clean machine.
saying these in an interview costs you the question
- Deleting Podfile.lock is the first fix for any pod install error
- Run sudo gem install cocoapods and ignore the Gemfile
- pod install can run before the JavaScript packages are installed
- Any Xcode version works as long as the simulator launches
- The last line of the pod install log is always the root cause