RORK LABJP
TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the roundTOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round
Articles/Dev Tools
Dev Tools/2026-04-24Intermediate

Diagnosing Metro Bundler Freezes and Broken Fast Refresh in Rork Apps

When your Rork-generated Expo app stops picking up code changes or Metro freezes mid-bundle, here is the diagnostic order and the safe reset steps that actually work.

Metro4Fast RefreshExpo149React Native209Troubleshooting38

You save a file. Nothing happens. The terminal looks alive, but your app is still showing the state from five minutes ago. If you have spent any real time with a Rork-generated Expo project, you know this feeling. What makes it frustrating is that the cause is almost never the same twice. Sometimes it is a stale cache, sometimes it is node_modules, sometimes it is Watchman hitting its file-watch ceiling.

Metro bundler and Fast Refresh issues are part of the React Native landscape. This article walks through the symptoms I keep running into, and the order in which to check things so you can get back to work in minutes rather than hours. I want to go beyond "clear the cache and pray" and actually explain why each step matters.

The Three Signals to Check First

When a Fast Refresh issue hits, there is a strong urge to immediately run rm -rf node_modules. Resist it for 30 seconds. Check these three things first, and you will usually know where the problem lives.

First, look at the Metro terminal output. Are you seeing BUNDLE or Hot update messages when you save a file? If yes, Metro itself is running — the problem is on the device side (the simulator or phone is not receiving updates). If no, Metro itself is stuck.

Second, check the path of the file you edited. Is it inside your project root? Did you accidentally modify a file inside node_modules? Is it a symlinked file? Metro only watches specific paths, and edits outside those paths will never trigger Fast Refresh. This one catches people more often than you would think.

Third, look for warnings. If Fast Refresh tried to run but gave up, you will often see a message like "Fast Refresh had to perform a full reload" either in the terminal or in your editor's console. That message points to a structural issue in your component code (more on this below).

The Five Reasons Metro Actually Freezes

In my experience, Metro freezes almost always trace back to one of these five root causes.

Corrupted or Bloated Cache

Metro stores intermediate artifacts in .expo/ and /tmp/metro-*. When these get corrupted, you get stale bundles even after saving your code. This happens especially often when you edit Rork-generated SwiftUI code directly in Xcode — external file changes confuse Metro's change detection.

Watchman File-Watch Limits

On macOS, Watchman monitors file changes, but the default per-process limit is 8,192 files. Monorepos or projects with heavy dependency graphs blow past this easily, and any changes beyond that limit are silently ignored.

Mismatch Between node_modules and Lockfile

Mixing npm install and yarn install, or reinstalling dependencies under a different Node.js version, leaves your node_modules out of sync with your lockfile. Metro tries to carry on, but certain module resolutions hang indefinitely.

Expo SDK Version Drift

When the Expo SDK version in app.json no longer matches the expo package version in package.json, Metro starts fine but hangs partway through bundling. This is common right after you update your app in Rork but leave the local copy on the old version.

Port Conflicts

Metro defaults to port 8081. If another process is holding it, Metro either moves to a different port or fails to start. The device-side app is still pointing at 8081, so you get a "Metro is running but won't connect" situation.

Diagnostic Flow by Symptom

Symptom A: Saves do not update the screen

Check the Metro log. If BUNDLE messages appear, the issue is on the device side. Manually reload the app (⌘R in the iOS simulator, shake the device or open the menu on Android). If a manual reload shows the latest code, then only Fast Refresh is broken — suspect your component structure.

If there is no BUNDLE message, Metro cannot detect your file changes. Restart Watchman first, it is the fastest fix.

# Reset Watchman state
watchman watch-del-all
watchman shutdown-server
 
# Restart Metro with a clean slate
npx expo start --clear

Expected output: after Starting Metro Bundler, you should see BUNDLE ./App.tsx. If it stalls here, move to the next step.

Symptom B: Metro hangs on "Loading dependency graph..."

Metro is stuck resolving dependencies. This is almost always a node_modules inconsistency. Clean up in a safe order:

# Step 1: Kill Metro and the simulator
# Ctrl+C to stop Metro, then quit the simulator
 
# Step 2: Remove caches and dependencies
rm -rf node_modules
rm -rf .expo
rm -f package-lock.json
 
# Step 3: Verify npm cache just in case
npm cache verify
 
# Step 4: Reinstall
npm install
 
# Step 5: Start with a cache clear
npx expo start --clear

Expected output: a QR code with Metro waiting on exp://192.168.x.x:8081.

Symptom C: "Fast Refresh had to perform a full reload" keeps appearing

This is a code-structure problem, not a tooling problem. Fast Refresh only handles "pure updates" in React function components. These patterns force a full reload:

  • Running side-effects at the top level of a file (like a bare console.log)
  • Multiple export default statements
  • Mixing class and function components in the same file
  • Anonymous functions as the default export (export default () => {})

The anonymous default export is especially sneaky. Rork sometimes generates them, and simply naming the function often fixes Fast Refresh.

// ❌ Breaks Fast Refresh
export default () => {
  return <View>...</View>
}
 
// ✅ Named function keeps Fast Refresh stable
export default function HomeScreen() {
  return <View>...</View>
}

The Full Reset Playbook (In Safe Order)

When nothing else works, here is the escalation ladder. Run each level, check if the issue is resolved, and only move on if it is not. You rarely need to go all the way.

#!/bin/bash
# rork-metro-reset.sh — escalate in safe order
 
# Level 1: Metro cache only (lightest)
npx expo start --clear
 
# Level 2: Reset Watchman too
watchman watch-del-all && watchman shutdown-server
npx expo start --clear
 
# Level 3: Blow away .expo and node_modules
rm -rf .expo node_modules
npm install
npx expo start --clear
 
# Level 4: Delete the lockfile to fully re-resolve
rm -rf .expo node_modules package-lock.json
npm install
npx expo start --clear
 
# Level 5: In the iOS simulator: Erase All Content and Settings
# Level 6: Delete Xcode DerivedData
rm -rf ~/Library/Developer/Xcode/DerivedData/*

Levels 3 and beyond mean long reinstalls, so you really want Levels 1 or 2 to do the job. In my own setup, Level 2 resolves about 80% of the issues I run into.

Preventing Recurrence with Better Project Hygiene

If the same symptom keeps coming back every week, the project setup itself is worth revisiting.

Make sure .expo/ is in .gitignore. On a team, one person accidentally committing their cache directory can poison every other developer's Metro instance.

Pin your Node.js version. Drop an .nvmrc at the project root so everyone installs against the same Node.js build. Subtle node_modules differences from version drift are a surprisingly common Metro-stall trigger.

# .nvmrc
20.11.0

Raise the Watchman limits on large projects. You can increase the number of watchable files on macOS with:

echo "kern.maxfiles=524288" | sudo tee -a /etc/sysctl.conf
echo "kern.maxfilesperproc=524288" | sudo tee -a /etc/sysctl.conf

A restart applies the changes. For heavy Expo apps or projects leaning on react-native-reanimated and other file-heavy libraries, this headroom pays off.

If you are hitting issues outside the Metro layer, the Expo dependency error fix guide and the complete build error guide cover the adjacent ground.

One Concrete Next Step

Metro problems are annoying precisely because they are hard to reproduce. To future-proof yourself, consider adding scripts/reset.sh to your project today, containing Levels 1 through 3 from above. When the next stall hits, you will be back at your editor in under a minute instead of breaking flow to recall the exact commands. Protecting momentum matters as much as the raw speedup. In my own workflow, this small addition has meaningfully reduced Metro-related stress.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-05-03
5 Things to Check First When Rork Shows 'Unable to Resolve Module'
Walk through the five most common causes of the 'Unable to resolve module' error in Rork, React Native, and Expo projects, with the exact commands and the order in which to check them.
Dev Tools2026-07-08
Your SVG Icon Shows in Expo Go but Vanishes in a Build — Making SVGs Render Reliably in Rork Apps
When a .svg import renders nothing, throws a resolve error, or ignores your theme colors in Rork and Expo apps, here is how to fix it with metro.config.js, react-native-svg-transformer, and currentColor — with working code.
Dev Tools2026-06-01
Fixing 'JavaScript heap out of memory' in Metro and EAS Builds
Your Rork or Expo build dies with 'FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory.' Here is why it happens and exactly how to fix it, both locally and on EAS Build.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →