You just installed a shiny new library, typed the import, and Metro throws Unable to resolve module in your face. I know the feeling—it's like the bundler is gaslighting you. The package is sitting right there in node_modules. So why can't it see it?
Let's fix it in order of how often I've seen it break. The cache is the usual suspect. Then the path. Then your config files.
Cause 1: Metro's stale cache is holding onto yesterday's module list
Metro caches the file tree and the haste map. When you install a new dependency, sometimes that cache doesn't refresh. It's a known gremlin, especially after npm install or yarn add runs while Metro is still watching.
The fix: Reset Metro's cache and start fresh
Close the Metro terminal (Ctrl+C). Then run this:
npx react-native start --reset-cache
If you're on Expo, use:
expo start --clear
Let it boot up, then reload your app. For iOS, press R twice in the simulator. For Android, press R in the Metro terminal. Give it a few seconds to rebuild the map.
If you're still seeing the error, skip the watchman and go nuclear:
watchman watch-del-all 2>/dev/null; rm -rf node_modules && npm install
Then start Metro with --reset-cache again. This combo has fixed more of these errors than any config change I've made.
Real-world trigger: You run npm install react-native-svg, then hit reload without restarting Metro. The bundler's file list hasn't picked up the new folder. This fix clears that stale list.
Cause 2: You're importing from the wrong path or the package name is off
Sometimes the error is your finger, not the computer. You typed import { Svg } from 'react-native-svg' but the package's main entry point is react-native-svg/lib/commonjs/index.js. Or you installed @react-native-community/slider but wrote Slider from '@react-native/slider'. Metro won't guess.
The fix: Check the package's real export path
Open node_modules/[package-name]/package.json. Look at the main and exports fields. That tells you the default entry point. Then make sure your import matches.
For example, if you see:
"main": "dist/index.js"
Your import should be the package name, and Metro will resolve to that file. But if the package has multiple subpaths, like react-native-vector-icons, you need the full subpath:
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
If you're unsure, check the package's README or its source on GitHub. I've wasted a full afternoon on a missing /lib suffix.
Real-world trigger: You installed react-native-webview and wrote import { WebView } from 'react-native-webview/src/WebView'. That path exists but isn't exported. Use react-native-webview alone.
Cause 3: Metro's config isn't looking in the right places
If you're using a monorepo, a custom metro.config.js, or an older React Native version, Metro might not be watching the folder where your new dependency lives. It defaults to looking at node_modules at the project root, plus your project's files. Anything outside that gets missed.
The fix: Edit metro.config.js to include the right folders
Open your metro.config.js (create it if it doesn't exist). You'll want to extend the watchFolders array. For a yarn workspace monorepo, it looks like this:
const { getDefaultConfig } = require('@react-native/metro-config');
const path = require('path');
const config = getDefaultConfig(__dirname);
config.watchFolders = [
path.resolve(__dirname, '..'), // go up one level to the workspace root
];
module.exports = config;
If you're on an older React Native (0.59 or below), the config format differs. You'll be using the blacklist and getBlacklistRE function. But that's rare now. If you're on Expo, you don't get a metro.config.js by default—you'd use metro.config.js only if you've ejected or used a plugin. For Expo, the fix is usually the cache clear first, then check your app.json for any custom nodeModulesPaths.
Real-world trigger: You're in a React Native monorepo with packages/app and packages/shared. You add a dependency to the root node_modules, but Metro only watches packages/app. The error appears. Setting watchFolders to the root fixes it.
Quick-reference summary
| Cause | Symptom | Fix |
|---|---|---|
| Stale Metro cache | Error appears right after install, before any reload | npx react-native start --reset-cache or expo start --clear |
| Wrong import path | Error includes a path that looks like src/ or lib/ |
Check package.json main and import using the package name only |
| Metro config missing folders | Error persists in monorepo or with custom config | Edit metro.config.js to add watchFolders |
Those cover 95% of the cases I've handled. If you're still stuck after all three, check for a typo in your import statement (case-sensitive, trust me), then verify the package actually installed by listing ls node_modules/[package-name]. And if you're using a new architecture, some packages aren't compatible yet—that's a different error message entirely, so watch for that.
Remember, Metro's error messages are usually honest—it genuinely can't find the module. But the reason is almost always one of these three. Start with the cache, check your path, then look at the config. You'll be back to building in minutes.
Now go build something cool. And if you've got a weird variant of this error, drop a comment below—I'm curious what new ways Metro finds to annoy us.