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-06-02Intermediate

Fixing 'No bundle URL present' on a Release Build to a Real iOS Device

How to read the 'No bundle URL present' error that shows up when you build a Rork-exported app locally in Xcode. We separate the Metro-connection case from the missing-embedded-bundle case, and walk through generating an offline bundle by hand with working commands.

Rork515Expo149iOS109Metro4Error Handling8

I wanted to add a WidgetKit extension to one of my wallpaper apps, so I opened the Expo project that Rork had exported in Xcode and installed a Release build onto my phone. The moment the splash screen disappeared, the screen filled with red text:

No bundle URL present.

Make sure you're running a packager server or have included a .jsbundle file in your application bundle.

It ran fine in the development build, so at first I blamed my own code. The real cause was earlier than that: the JavaScript simply wasn't anywhere the app could find it. You may have seen the same red screen in a Debug build, but Debug and Release fail for completely different reasons. Mix them up and you lose half a day. I did.

What the error is actually telling you

No bundle URL present means the native side of the iOS app has no idea where to load JavaScript from at launch. A React Native / Expo app runs a JavaScript bundle inside a native shell, and that bundle can live in one of two places.

  • Debug build: it connects to the Metro bundler running on your Mac at http://<your-mac-ip>:8081 and loads the JS over the network
  • Release build: it loads from a main.jsbundle file baked into the app itself

The red screen means neither of those was found. So the very first thing to determine is whether it happened in Debug or Release.

If it happened in a Debug build — Metro isn't reachable

If your scheme was still set to Debug when you installed onto the device, this is almost always a Metro connection problem. In order of how often I hit each:

  1. Metro isn't running. Forgetting to start npx expo start in a terminal is the most common trap of all.
  2. The Mac and the iPhone are on different Wi-Fi networks. A physical device can't reach your Mac via localhost. Same network is the baseline requirement.
  3. The router blocks device-to-device traffic. Guest SSIDs and "client isolation" settings stop the connection even when both devices show the same network name.

The quick check: open http://<your-mac-ip>:8081/status in Safari on the iPhone. If it returns packager-status:running, the route is alive and the problem is elsewhere. If nothing comes back, it's a network issue.

The most reliable path is to connect the device over USB and reinstall with:

# With the device connected over USB, this forwards the port and launches it
npx expo run:ios --device

expo run:ios resolves the device and handles the Metro port for you. On flaky Wi-Fi this is by far the least painful option.

If it happened in a Release build — the bundle wasn't baked in

This is the real subject. A Release configuration never talks to Metro. The app must contain a main.jsbundle, and without it you get the red screen. This is exactly where people who start editing a Rork-exported project locally in Xcode get stuck.

There are two main causes.

1. The bundling build phase didn't run

A React Native iOS project has a shell-script build phase called "Bundle React Native code and images" that packages the JS at build time. A clean project from Expo prebuild includes it, but while hand-editing native code you can accidentally set it to skip, or the script's reference paths can drift, and then no bundle is produced even in Release.

In Xcode, open the target → Build Phases and confirm the Bundle React Native code and images phase exists and that Run script only when installing is unchecked. When it's checked, the script runs only during Archive, not on a normal Run — which produces the confusing symptom "red screen on device, but Archive works fine."

2. You aren't using expo run:ios --configuration Release

Rather than hitting raw xcodebuild or Xcode's Run in Release, it's more reliable to let Expo handle the Release build.

# Let Expo do the Release build, bundle embedding included
npx expo run:ios --configuration Release --device

This command generates the bundle and embeds it before installing to the device, so you spend far less time fighting manual build-phase settings.

A stopgap — building the offline bundle by hand

When you just want it running on a device right now, before touching build-phase settings, you can generate the bundle manually and drop it into the project.

# Generate main.jsbundle and assets under the ios directory
npx react-native bundle \
  --platform ios \
  --dev false \
  --entry-file index.js \
  --bundle-output ios/main.jsbundle \
  --assets-dest ios

On projects using Expo Router, --entry-file may need to be node_modules/expo-router/entry.js. If it complains it can't find the entry, check the main field in package.json. Add the generated main.jsbundle to the target in Xcode (not as a folder reference), and Release builds will read from it.

But treat this strictly as a stopgap. A hand-placed bundle doesn't auto-update when you change code, so once you've fixed the real cause (the build phase), remove the manual bundle. I stepped on this trap a few times and caused a secondary mess — "it worked!" while an old JS bundle was still baked in — so I'll say it plainly.

The order I work through it (when in doubt, follow this)

When I see the red screen, I always knock it down in this order.

  1. Is the configuration Debug or Release? (check the scheme at the top-left of Xcode)
  2. If Debug: is Metro running, and are the device and Mac on the same Wi-Fi?
  3. If Release: does Build Phases include the bundling phase, and is only when installing unchecked?
  4. Still failing? Rebuild with expo run:ios --configuration Release --device
  5. If you need a working build faster than a root-cause fix, generate the offline bundle by hand

Following that order alone keeps you from the detour of distrusting your code and reading logs endlessly.

Prevention — so you never lose half a day again

I've run apps with over 50 million cumulative downloads as a solo developer since 2014, and I often split the work: scaffold quickly in Rork, then add only the native pieces — WidgetKit, Live Activities — in Xcode. Once I made it a habit to verify on a real device in Release every time, this error stopped stopping me. Don't conclude "it works" from the dev build alone; install the store configuration (Release) onto a real device at least once. That one habit prevents the panic moments right before review.

Try installing your current project onto a device with npx expo run:ios --configuration Release --device. If no red screen appears there, your distribution build is carrying its bundle correctly. I hope this helps anyone stuck at the same spot.

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-06-29
Handling iOS Limited Photo Library Access in a Rork (Expo) App
Handle iOS limited photo library access (selected photos only) correctly in a Rork (Expo) app. Covers the three states of full / limited / denied, designing a screen that works from the selected subset, and a path to add more photos, all with working code.
Dev Tools2026-06-26
Import the User's Own Image From the Files App in a Rork App, Without the URL Going Stale
Pull images from the Files app or iCloud Drive and the URL you picked goes invalid moments later. Here is how expo-document-picker, security-scoped URLs, and a reliable copy into your sandbox actually work, with running code.
Dev Tools2026-06-15
Putting a Working Button in a Rork App's Widget — Implementing App Intents So a Tap Acts Without Opening the App
How to put a button in a Rork-generated Expo app's widget that changes state without launching the app. We wire App Intents and WidgetKit together through an App Group, all the way to reloadTimelines — including the two places I lost real time.
📚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 →