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-05-23Intermediate

Rork-Specific 'expo start --offline forbidden': Four Causes in Rork's Template Config

When expo start --offline returns 'forbidden' specifically on a Rork-generated project, the cause is usually Rork template config: tsconfigPaths, an un-generated expo-router cache, native prebuild, or a lockfile mismatch. Four Rork-specific fixes; the generic Expo proxy and dependency-validation guide is covered separately.

rork58expo11expo-offlinetroubleshooting65react-native12

You hop on a plane, want to keep iterating on the Rork prototype you started yesterday, type EXPO_OFFLINE=1 expo start --offline — and the CLI dies with Setting EXPO_NO_DEPENDENCY_VALIDATION or skipping validation via flags is forbidden in this environment. I'm Masaki Hirokawa, an indie developer running an iOS / Android app business since 2014 (collectively over 50 million downloads). Lately I've been using Rork for fast prototypes and testing them in offline-only environments — planes, exhibition halls, low-bandwidth trips — which is exactly where this error keeps showing up.

It's the collision between Expo CLI's safety net and Rork's default template configuration. Simply dropping --offline is not the fix. Triaged in the right order, every case has a clean path through.

What the error actually is — env vars and flags fighting for priority

Since Expo CLI 53, expo start validates that installed package versions match the SDK's expectations. Useful in normal use; awkward when you combine flags to go fully offline:

# The combination that triggers "forbidden" on Rork projects
EXPO_OFFLINE=1 EXPO_NO_DEPENDENCY_VALIDATION=1 expo start --offline

The CLI maintains an internal list of "environments where skipping validation must not be allowed." When Rork's generated app.json matches certain shapes (more below), the CLI refuses your implicit or explicit attempt to skip validation and aborts with forbidden. You only wanted "no network," but the CLI heard "also turn off the safety check," and said no.

First move: see where 'forbidden' actually fires

Same wording, multiple sources. The first thing to do is re-run with verbose logs and look at the lines immediately before the failure.

# Verbose logs, captured to a file for inspection
EXPO_DEBUG=1 EXPO_OFFLINE=1 expo start --offline --verbose 2>&1 | tee /tmp/expo-start.log
grep -B5 'forbidden' /tmp/expo-start.log | tail -20

In my experience the last few lines before forbidden always mention either validateDependenciesVersions (internal auto-skip path) or EXPO_NO_DEPENDENCY_VALIDATION (you set it explicitly). That distinction tells you which cause you're chasing.

Cause 1: Rork's expo.experiments.tsconfigPaths is on

Recent Rork templates set expo.experiments.tsconfigPaths: true in app.json. When that's on, Expo CLI refuses to auto-skip validation during --offline because TypeScript path resolution depends on it.

// app.json — typical shape generated by Rork
{
  "expo": {
    "name": "MyRorkApp",
    "experiments": {
      "tsconfigPaths": true,
      "typedRoutes": true
    },
    "plugins": [
      "expo-router",
      "expo-font"
    ]
  }
}

Two paths through this: drop --offline and use expo start --no-dev --minify instead, or temporarily flip those experiments off for the offline session. For venue-side emergency starts I keep this script around:

#!/usr/bin/env bash
# scripts/expo-offline-safe.sh — start a Rork project safely offline
set -euo pipefail
 
cp app.json app.json.backup
 
# Temporarily disable tsconfigPaths and typedRoutes
node -e "
  const fs = require('fs');
  const j = JSON.parse(fs.readFileSync('app.json', 'utf8'));
  if (j.expo && j.expo.experiments) {
    j.expo.experiments.tsconfigPaths = false;
    j.expo.experiments.typedRoutes = false;
  }
  fs.writeFileSync('app.json', JSON.stringify(j, null, 2));
"
 
trap "mv app.json.backup app.json" EXIT
 
EXPO_OFFLINE=1 expo start --offline

The trap that restores app.json on exit is the important bit — without it you'll forget you turned the experiments off and spend tomorrow wondering why typed routes broke.

Cause 2: expo-router cache hasn't been generated yet

A fresh-clone Rork project using Expo Router won't have .expo/types/router.d.ts yet. On first offline start, the CLI declares "I need online access to generate this cache" and returns forbidden.

Run one online start to materialize the cache, then go offline:

# Run online once to generate the cache (Ctrl-C after 10–30s is fine)
expo start --tunnel
# Verify the cache exists
ls -la .expo/types/
# Now offline works
EXPO_OFFLINE=1 expo start --offline

If .expo/ is in your .gitignore, every fresh clone needs this one-time online warmup.

Cause 3: Native prebuild hasn't run

If the project pulls in native modules like expo-haptics or expo-image and you haven't run npx expo prebuild, validateDependenciesVersions tries to compare against a non-existent native version and falls over.

Spot it: /tmp/expo-start.log mentions ios/ or android/. If yes, prebuild first:

# Prebuild without installing, then restart
npx expo prebuild --no-install
EXPO_OFFLINE=1 expo start --offline

--no-install is intentional — you don't want pod install or Gradle sync attempting network operations while offline. The prebuild alone gives the validator something to compare against, and forbidden goes away.

Cause 4: Lockfile drift in pnpm / bun

On Rork projects using pnpm or bun, a package.json that has drifted from its lockfile makes the CLI distrust the resolved versions and respond with forbidden.

# Verify lockfile is in sync with package.json
pnpm install --frozen-lockfile  # for pnpm
bun install --frozen-lockfile   # for bun

If --frozen-lockfile fails, the lockfile is stale. Run a normal install online to refresh it, then retry the offline start.

Triage order

Any of the four can fire alone or together. The order I run:

First, look at the EXPO_DEBUG=1 log for tsconfigPaths — that's cause 1. If absent, check .expo/types/ for the router cache — cause 2. Then check whether ios/ and android/ directories exist — cause 3. Finally verify lockfile sync — cause 4.

Following that order avoids unnecessary prebuilds and tunnel restarts, and I can usually resolve forbidden in under five minutes even on flaky travel Wi-Fi.

A durable fix: package.json scripts

I don't trust myself to remember these commands, so I keep them in package.json:

{
  "scripts": {
    "start": "expo start",
    "start:online-cache": "expo start --tunnel",
    "start:offline-safe": "bash scripts/expo-offline-safe.sh",
    "rebuild:native": "npx expo prebuild --clean --no-install",
    "lock:sync": "pnpm install --frozen-lockfile || pnpm install"
  }
}

The pattern on a freshly cloned Rork project: npm run start:online-cache for 30 seconds to warm caches, then npm run start:offline-safe for everything else. With this combo I've had zero offline startup failures across the last several exhibition trips, even when the venue Wi-Fi was unreliable.

Stay aware of Rork's template defaults

The four causes above are general Expo knowledge, but Rork's template defaults change over time. The expo.experiments block sometimes ships with tsconfigPaths and typedRoutes set to true and sometimes to false, depending on when you generated the project. That single difference flips how prone you are to forbidden.

When you scaffold a new Rork project, eyeball app.jsonexpo.experiments first and decide whether it lines up with your offline plans. I recommend making that a habit — in my experience it's the single check that cuts offline-side troubleshooting time the most.

What to try next

Once offline startup is stable, the next two things worth checking are Hot Reload behavior offline and Metro's bundler cache management. Knowing when to clear .expo/cache/ keeps long-trip development calm. Thanks for reading.

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-03-26
Rork React Native Build Errors: Complete Troubleshooting Guide
Master React Native build failures in Rork. From Metro crashes to Gradle and Xcode errors, learn the root causes and step-by-step fixes for every common scenario.
Dev Tools2026-05-24
Why your Rork app shows a blank screen or loses state after returning from background
Your Rork app sits in the background overnight, you tap the icon the next morning, and the screen is blank — or your drafts have disappeared, or you have been silently logged out. iOS process reclamation, AsyncStorage rehydration timing, and Navigation state restoration each cause a different version of this bug. Notes from running wallpaper and wellness apps with 50M downloads as an indie developer.
Dev Tools2026-05-20
Fixing 0x8badf00d Watchdog Kills That Wipe Out Rork Apps at Launch
Your Rork iOS app dies right after launch on real devices. Crashlytics shows exception code 0x8badf00d. Here is the watchdog termination story and the exact steps an indie developer running React Native apps for 50M downloads uses to make it stop.
📚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 →