If you've worked with React Native for a while, you've probably run into a problem where Metro refuses to start, gets stuck while bundling, or leaves your app waiting for JavaScript that never arrives.
Sometimes the terminal shows an error immediately. Other times, Metro appears to start normally, but the app stays on a loading screen or fails to connect to the development server.
The frustrating part is that these symptoms can have completely different causes. A port conflict, stale cache, broken dependency installation, invalid configuration, or network issue can all look like a Metro problem.
Here's how to narrow it down and fix the actual cause instead of repeatedly restarting your project and hoping something changes.
1. Identify What Metro Is Actually Doing
Before changing anything, identify which of these situations matches your problem.
- Metro won't start: The development server exits with an error, refuses to launch, or reports that a port is already in use.
- Metro starts but gets stuck bundling: The terminal shows that bundling has started, but it never finishes.
- The app cannot connect to Metro: The server appears to be running, but the application displays a loading screen or a connection error.
- Metro starts, but the app crashes: Bundling may be successful, but a JavaScript exception or native configuration problem prevents the app from running.
These are different failure points. Clearing the cache might help with a stale bundle, but it won't fix a port occupied by another process or an invalid native configuration.
Start with the simplest checks and move toward more disruptive fixes only when necessary.
2. Stop Metro and Start It Again
First, stop any Metro server running in the terminal by pressing Ctrl + C.
Then start it using the command appropriate for your project.
If you're using Expo
From your project directory, run:
npx expo start
To clear Expo's Metro cache at the same time, use:
npx expo start --clear
If you're using React Native CLI
Start Metro from your project's root directory:
npx react-native start
If you suspect stale cached files, use:
npx react-native start --reset-cache
Important: You don't need to clear the cache every time Metro fails. Start with the normal command. Use the cache-reset option when the symptoms suggest stale or inconsistent cached data, or when a normal restart doesn't help.
If Metro exits immediately, read the terminal output before trying another command. The first meaningful error is often more useful than the final stack trace.
3. Check Whether Port 8081 Is Already in Use
Metro normally uses port 8081. If another process is listening on that port, Metro may fail to start or ask you to use a different one.
The terminal might show a message similar to:
Error: listen EADDRINUSE: address already in use :::8081
This means another process is already using the requested address and port.
On Windows
Open Command Prompt and run:
netstat -ano | findstr :8081
Look for a line containing LISTENING. The last column contains the process ID (PID).
You can identify the process with:
tasklist /FI "PID eq 12345"
Replace 12345 with the actual PID.
If you've confirmed that the process is an old Metro server you no longer need, you can stop it:
taskkill /PID 12345 /F
On macOS or Linux
Run:
lsof -i :8081
Inspect the process listed for port 8081. If it's an old Metro process that you no longer need, stop that specific process:
kill <PID>
Replace <PID> with the actual process ID.
Don't terminate a process simply because it's using the port. Confirm what it is first, especially if other development tools are running.
Once the port is available, start Metro again.
4. Clear Metro's Cache When Bundling Gets Stuck
Metro transforms your JavaScript files and their dependencies into a bundle the application can execute. Cached transformation results help make subsequent builds faster, but stale or inconsistent cached data can sometimes cause confusing behavior.
Typical symptoms include:
- Bundling worked before, but now fails after code or dependency changes.
- The app appears to use an older version of your JavaScript.
- Metro repeatedly fails while transforming files without an obvious dependency error.
- A normal restart doesn't resolve the problem.
Try the appropriate cache-reset command from Step 2.
After the cache is cleared, let Metro rebuild the bundle. The first build can take longer because the cached transformation results need to be regenerated.
If the same error returns, don't keep clearing the cache. Look at the specific file, dependency, or configuration mentioned in the terminal output. A repeatable error usually means there's something more specific to fix.
5. Check Your Dependencies Before Reinstalling Everything
Metro depends on the packages and configuration in your React Native project. If a package installation was interrupted, dependencies were changed, or incompatible versions were introduced, Metro may fail while loading its configuration or resolving modules.
Start by checking the actual error.
For example, these messages point toward different problems:
Cannot find module ...
Unable to resolve module ...
Cannot find module 'metro-config'
A missing module doesn't automatically mean the entire dependency installation is broken. It might be an incorrect import path, a package that was never installed, or a version mismatch.
Check the following:
- Did the problem start immediately after installing, removing, or updating a package?
- Does the error identify a particular module or package?
- Does your project use the package versions expected by its React Native or Expo version?
- Did you accidentally run the installation command from the wrong directory?
If the project uses npm and has a valid, committed package-lock.json, a clean installation may be appropriate:
npm ci
This reinstalls dependencies according to the lockfile and removes the existing node_modules directory as part of the process.
For a Yarn project, use the installation command appropriate for its Yarn version and existing lockfile. Don't switch package managers or delete your lockfile just to see whether Metro starts.
Avoid deleting node_modules, lockfiles, and caches all at once as your first response. Doing so can introduce new version differences and make it harder to identify what originally caused the failure.
6. Check Metro and Expo Configuration
If Metro reports an error while loading its configuration, clearing the cache or reinstalling dependencies might not help.
Look for changes to files such as:
metro.config.jsbabel.config.jspackage.json- Expo app configuration, such as
app.jsonorapp.config.js
Pay particular attention to recent changes involving custom Metro configuration, Babel plugins, aliases, monorepo settings, or package versions.
For example, if Metro fails while loading metro.config.js, inspect the configuration and the package named in the error. A missing import or incompatible configuration dependency can prevent the server from starting at all.
If the problem appeared after a configuration change, compare that change with the last working version. Reverting one recent change is often more informative than rebuilding the entire environment.
For Expo projects, also make sure you're following the configuration requirements for your installed Expo SDK rather than copying a Metro configuration from an unrelated project or older tutorial.
7. If Metro Runs but the App Cannot Connect
A running Metro server doesn't guarantee that your app can reach it.
This distinction matters because repeatedly resetting Metro's cache won't fix a connection problem.
Check the development-server URL
When Metro starts, inspect the URL or connection information it prints in the terminal.
If you're using a physical device, make sure the device and computer can communicate over the selected network. VPNs, firewalls, guest Wi-Fi networks, and network isolation can interfere with local development connections.
If you're using Expo
Expo supports different connection methods depending on your environment and configuration. If the normal connection method doesn't work, try the tunnel option:
npx expo start --tunnel
A tunnel can help when the device cannot reach your computer directly over the local network, although it may be slower and depends on the tunnel service being available.
If you're using an Android emulator
Check that the emulator is running and that the development server is reachable. For a React Native CLI workflow using the standard Android emulator setup, you can forward port 8081 with:
adb reverse tcp:8081 tcp:8081
This is useful when the emulator needs a route to Metro through Android Debug Bridge. It isn't a universal fix for every device or connection setup.
If the app can connect but crashes after loading the bundle, move on to the JavaScript or native error shown by the app. At that point, Metro itself might be working correctly.
8. Don't Confuse a JavaScript Error With a Metro Startup Failure
Sometimes developers blame Metro because the application stops working immediately after a successful bundle.
But these messages describe different problems:
- Metro startup error: The development server cannot initialize.
- Module resolution error: Metro cannot find or resolve a requested module.
- JavaScript runtime exception: The bundle loads, but the application encounters an error while executing code.
- Native build error: The Android or iOS application fails during native compilation or configuration.
For example, if Metro reports that it cannot resolve a module imported by App.tsx, investigate the import path, filename, package installation, and any configured aliases.
If the Android build fails before the application starts, inspect the native build output instead of treating every failure as a Metro cache problem.
Finding the correct failure point saves time because each category requires a different solution.
9. When None of These Fixes Works
If Metro still refuses to start, collect the evidence before making more changes.
A useful troubleshooting report should include:
- The exact command used to start Metro.
- The full terminal error, especially the first meaningful error before the stack trace.
- Your operating system.
- Whether the project uses Expo or React Native CLI.
- The relevant React Native and Expo versions.
- Any recent dependency or configuration changes.
- Whether Metro fails to start, gets stuck bundling, or starts while the app cannot connect.
Remove access tokens, passwords, private URLs, and other sensitive information before sharing logs publicly.
If the output contains several errors, don't assume the final message is the root cause. A failure to load one configuration dependency can trigger multiple follow-up errors.
This is also where a diagnostic tool can help. If you've already tried the obvious fixes and the logs are difficult to interpret, you can paste the relevant error and technical context into FixMyError. It can help analyze the failure, identify likely causes, and suggest targeted next steps instead of making you cycle through unrelated fixes.
Final Thoughts
When Metro Bundler gets stuck or refuses to start, the best approach is to identify where the failure occurs before changing your project.
Start with a normal restart, check port 8081, clear the cache when appropriate, and inspect dependency or configuration errors when they appear. If Metro is running but the app cannot connect, troubleshoot the connection rather than repeatedly resetting the bundler.
The goal isn't to run every possible fix. It's to find the specific reason your development environment stopped working and make the smallest change that resolves it.
Top comments (1)
Section 8 is the one I wish more guides had. Two errors that look like Metro problems but need a different fix:
adb reverse tcp:8081 tcp:8081; on Wi-Fi, set your computer's IP and port 8081 in the dev menu. In a release build it means the JS bundle was never packaged, so restarting Metro won't help.Disclosure: I maintain an open-source CLI that reads Metro or logcat output and says which of these you're looking at:
npx rn-build-doctor analyze metro.log(run it from the project folder so it can check package.json and node_modules): github.com/lassiecoder/rn-build-do...