If you have ever developed a React Native or Expo app, you have almost certainly seen this red screen: `Unable to resolve module 'xyz' from '/path/to/file.tsx'`. This is the single most Googled React Native error — and it has been for years. The frustrating part is that the fix is different depending on what caused it. This guide covers every root cause and its exact solution in one place.
What This Error Actually Means
Metro is the JavaScript bundler that powers React Native and Expo. When you start your app, Metro walks through every import statement in your code and builds a complete dependency graph. The moment it hits an import it cannot locate — whether because the package is missing, the path is wrong, the cache is stale, or the module requires native code not available in your environment — it stops immediately and throws `Unable to resolve module`. The error message always includes the module name it could not find and the file it was imported from, which is your starting point for debugging.
Cause 1: Stale Metro Cache (Most Common)
Metro caches transformed modules locally for speed. After you install a new package, add a file, or change a config, Metro sometimes keeps serving the old cached state and cannot resolve the new module even though it is physically present in `node_modules`. This is the most common cause of this error and the fix takes five seconds.
If the error persists after clearing the cache, move on to the next cause — the cache was not the issue.
Cause 2: Package Not Installed
The most obvious cause — you are importing a package that is not in your `node_modules`. This happens when you copy code from documentation, a tutorial, or an AI tool without installing the dependency first. Check the exact module name in the error and install it.
For Expo projects specifically, always use `npx expo install` instead of plain `npm install`. The Expo CLI picks the exact version compatible with your installed SDK, which prevents a whole class of follow-up version mismatch errors.
Cause 3: Wrong Import Path (Typo or Case Mismatch)
If you are importing a local file (not a package), a wrong path or file name case mismatch will trigger this error. macOS is case-insensitive but Linux (used by CI and EAS Build) is case-sensitive — so a file named `Button.tsx` imported as `button.tsx` works on your Mac but fails in production builds.
Cause 4: Mixed Up Default and Named Imports
A very common mistake is using a default import for a named export or vice versa. Metro resolves the module file but cannot match the import to an export, which surfaces as an `Unable to resolve` or `undefined` error depending on the library.
Cause 5: Native Module Used in Expo Go
Libraries that ship native code (C++, Swift, Kotlin) cannot run inside Expo Go because Expo Go only bundles a fixed set of pre-compiled native modules. If you try to use a library like `react-native-vision-camera`, `react-native-mmkv`, or `react-native-maps` in Expo Go, Metro resolves the JS file but the native binary is missing, causing the error. The fix is to switch from Expo Go to a Development Build.
Cause 6: node_modules Corrupted or Out of Sync
Sometimes `node_modules` gets into a broken state after a failed install, a git pull that changed `package.json`, or switching branches. A full clean reinstall fixes this.
Cause 7: iOS Pods Not Installed After Adding a Package
In bare React Native projects on iOS, installing a native package with `npm install` is not enough — CocoaPods must also be updated to link the native side. Forgetting `pod install` after adding a native library is one of the most common causes of this error on iOS specifically.
Cause 8: Expo SDK Version Mismatch
If you installed a package with plain `npm install` in an Expo project, it may pull a version incompatible with your SDK. This causes Metro to resolve the module but then fail to run it. Always use `npx expo install` and run the version check regularly.
Quick Diagnosis Checklist
- Clear Metro cache first — `npx expo start --clear`. If it fixes it, you are done.
- Check the module name in the error — is it a package or a local file path? If it is a package, confirm it is in your `package.json` and `node_modules`.
- If the package exists but error persists — delete `node_modules` and reinstall cleanly.
- If it is a local file — verify the exact filename, folder structure, and casing matches your import.
- If you just added a native library and are on Expo Go — switch to a development build.
- If you are on iOS bare workflow — run `pod install` inside the `ios/` folder.
- Run `npx expo-doctor` — it catches version mismatches and missing peer dependencies automatically.
Official-Style Error Explanation
`Unable to resolve module 'xyz' from '/path/to/file.tsx'` means Metro, the React Native JavaScript bundler, encountered an import it could not locate while building the dependency graph. The root cause is one of eight things: stale cache, package not installed, wrong local file path, case mismatch in filename, mixed default and named imports, native module not available in Expo Go, corrupted node_modules, or an SDK version mismatch. Always start by clearing the Metro cache with `npx expo start --clear`, then check whether the package is installed and whether the import path is correct. For Expo projects, use `npx expo install` instead of `npm install` to pin the correct SDK-compatible version automatically.
FAQ
The package is in node_modules but I still get the error — why?
Metro is almost certainly serving a stale cached version that does not know about the newly installed package. Run `npx expo start --clear` or `npx react-native start --reset-cache` to force Metro to rebuild its module graph from scratch.
The error only happens in my EAS Build / CI but not locally — why?
This is almost always a filename case mismatch. Your local macOS filesystem is case-insensitive, so `import Button from './button'` resolves `Button.tsx` without error. Linux (used by EAS Build and most CI environments) is case-sensitive and rejects the wrong casing. Fix your import to exactly match the filename.
How do I know if a library needs a Development Build vs working in Expo Go?
Check the library's README — anything mentioning 'Custom Development Client required', native modules, iOS/Android setup steps, or config plugins needs a Development Build. You can also check reactnative.directory which marks each library's Expo Go compatibility status.
I deleted node_modules and reinstalled but still get the error — what next?
Clear everything: delete node_modules, package-lock.json, the .expo folder, and the Metro cache temp files, then reinstall. On macOS: `rm -rf node_modules .expo && npm cache clean --force && npm install && npx expo start --clear`. If it still fails, run `npx expo-doctor` to identify any dependency conflicts or incompatible versions.