RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-05-23中級

Rork 生成プロジェクト特有の expo start --offline forbidden — テンプレ構成が原因の4パターン

Rork が生成するテンプレート構成が原因で expo start --offline が forbidden になる4つのパターン(tsconfigPaths・expo-router キャッシュ・ネイティブプリビルド・lock 不一致)を、Rork プロジェクト固有の観点で切り分けます。汎用的な Expo 側の対処(プロキシ403・依存検証)は別記事にまとめています。

rork58expo11expo-offlinetroubleshooting25react-native12

オフライン環境で Rork プロジェクトを動かそうとして EXPO_OFFLINE=1 expo start --offline と叩いた瞬間に、Setting EXPO_NO_DEPENDENCY_VALIDATION or skipping validation via flags is forbidden in this environment という赤いエラーで止まった、という経験はないでしょうか。アーティスト・クリエイターの廣川政樹です。個人開発で iOS / Android アプリ事業を 2014 年から続けており、累計 5,000 万ダウンロードを超えたアプリ群の試作や検証で、最近は Rork でプロトタイプを高速に組み、機内・出張中・展示会場のオフライン環境で挙動を確かめる機会が増えました。

このエラーは Expo CLI 側の防御機構が Rork のテンプレート構成と衝突して発生するもので、単に --offline を外せば動くというものでもありません。順を追って原因を切り分けると、必ず通る経路が見えてきます。

エラーの正体は「環境変数とフラグの優先順位」のぶつかり合い

Expo CLI 53 以降、expo start には依存関係のバージョン整合性を起動時にチェックする仕組みが入りました。これは Expo SDK の前提とインストール済みパッケージのバージョンが食い違う問題を早期に検出する機構で、通常は歓迎すべき機能です。ところが、オフライン環境で起動するために以下のような組み合わせを使うと衝突します。

# 衝突する組み合わせ — Rork プロジェクトで forbidden が出る
EXPO_OFFLINE=1 EXPO_NO_DEPENDENCY_VALIDATION=1 expo start --offline

Expo CLI は EXPO_NO_DEPENDENCY_VALIDATION--skip-validation 系のフラグを「安全のため有効にしてはいけない環境」を内部的に判定しており、Rork が生成する app.json の特定の構成(後述)に該当すると、このバリデーションスキップ自体を forbidden として拒否します。--offline で「ネットワーク不要モード」で起動したいだけなのに、暗黙にバリデーションを切ろうとしてエラーになる、というのが本質です。

切り分けの最初の一手 — どこで forbidden が起きているか確認

エラーメッセージは似ていても、出元が違うことがあります。最初にやるのは、expo start のログを --verbose 付きで取り直して、forbidden の直前に何が走っているかを見ることです。

# 詳細ログ付きで起動して、どこで forbidden になるかを確認
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

私の経験では、forbidden が出る前の最後の数行に必ず validateDependenciesVersionsEXPO_NO_DEPENDENCY_VALIDATION のどちらかが現れます。前者の場合は CLI 内部の自動スキップ判定、後者の場合は環境変数を明示的に立てていた、というように原因がはっきり分かれます。

原因 1: Rork テンプレの expo.experiments.tsconfigPaths 構成

Rork の最近のテンプレートは、app.jsonexpo.experiments.tsconfigPaths: true を含めることが多いです。この設定が入っていると、Expo CLI が「TypeScript パス解決を行う前にバリデーションをスキップしてはいけない」と判定し、--offline での自動スキップを拒否します。

// app.json — Rork が生成する典型構成
{
  "expo": {
    "name": "MyRorkApp",
    "experiments": {
      "tsconfigPaths": true,
      "typedRoutes": true
    },
    "plugins": [
      "expo-router",
      "expo-font"
    ]
  }
}

このケースの対処は、--offline を外して expo start --no-dev --minify を使う方法と、tsconfigPaths を一時的に無効化してオフライン起動する方法のどちらかです。展示会場での緊急回避なら後者が早いので、私は次のスクリプトを使い回しています。

#!/usr/bin/env bash
# scripts/expo-offline-safe.sh — Rork プロジェクトをオフラインで安全に起動
set -euo pipefail
 
cp app.json app.json.backup
 
# tsconfigPaths と 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

trap で終了時に元の app.json を復元する点が要です。設定を戻し忘れて翌日のオンライン開発でハマる、という二次被害を防げます。

原因 2: expo-router のキャッシュ未生成

Expo Router を使っている Rork プロジェクトを初回オフライン起動すると、ルーティングテーブルのキャッシュが .expo/types/router.d.ts に存在せず、CLI が「キャッシュ生成のためにオンラインアクセスが必要」と判定して forbidden を返すことがあります。

対処は、一度オンラインで expo start を完走させてキャッシュを作ってから、オフラインに切り替えることです。具体的には次の順で叩きます。

# 一度オンラインで起動してキャッシュ生成(10〜30 秒で Ctrl-C して OK)
expo start --tunnel
# キャッシュが作られているか確認
ls -la .expo/types/
# 確認できたらオフライン起動
EXPO_OFFLINE=1 expo start --offline

.expo/types/router.d.ts が生成されていれば、次回からはオフラインでも起動が通ります。.expo/ 配下を .gitignore で除外している場合、新しいクローン直後は必ずこの初回オンライン起動が必要です。

原因 3: ネイティブモジュールのプリビルド未完了

Rork が生成するプロジェクトに expo-hapticsexpo-image のようなネイティブモジュールが入っていて、npx expo prebuild を実行していない状態でオフライン起動を試みると、validateDependenciesVersions がプリビルド済みのネイティブバージョンと比較しようとして失敗します。

このパターンの判定は、/tmp/expo-start.log の中に ios/android/ フォルダへのアクセスが出ているかで分かります。出ていればプリビルドが必要です。

# プリビルドを実行してから再起動
npx expo prebuild --no-install
EXPO_OFFLINE=1 expo start --offline

--no-install を付けるのは、オフラインで pod install / Gradle 同期が動いて失敗するのを防ぐためです。プリビルドだけ済ませれば、validateDependenciesVersions の比較対象が揃って forbidden が消えます。

原因 4: パッケージマネージャの lock ファイル不一致

pnpm や bun を使っている Rork プロジェクトで、package.json と lock ファイルがずれていると、Expo CLI のバリデーションが lock ファイル側の値を信頼できないと判定して forbidden を返す場合があります。

# lock ファイルと package.json が同期しているか確認
pnpm install --frozen-lockfile  # pnpm の場合
bun install --frozen-lockfile   # bun の場合

--frozen-lockfile で失敗するなら、lock ファイルが古い証拠です。一度オンラインで pnpm installbun install を走らせて lock を更新してから、再度オフライン起動を試します。

切り分けの順序

4 つの原因はどれも単独でも組み合わせでも起きます。私が回している順序は次の通りです。

最初に EXPO_DEBUG=1 でログを取り、tsconfigPaths が出ているなら原因 1。出ていなければ .expo/types/ の有無で原因 2 を切り分け。次に ios/ android/ フォルダの存在で原因 3 を確認。最後に lock ファイルで原因 4 を確認、という順序です。

この順序を守ると、必要のないプリビルドや tunnel 起動を回避できるので、特に出張先の弱い回線でも 5 分以内に解消できます。

恒久対策: package.json scripts に整理しておく

毎回コマンドを思い出すのは現実的ではないので、私は次のような scripts を 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"
  }
}

新しいマシンに Rork プロジェクトを clone した直後の流れは、npm run start:online-cache で 30 秒走らせてキャッシュを作り、その後はずっと npm run start:offline-safe を使う、という運用に落ち着きました。展示会場で会場 Wi-Fi が不安定なときも、この組み合わせで起動失敗ゼロを維持できています。

Rork 側の生成テンプレートを意識した対処を選ぶ

ここまで挙げた 4 原因はどれも Expo 側の汎用知識ですが、Rork で生成したプロジェクト特有の事情として、テンプレートの expo.experiments 設定が変わると挙動が変わる点には注意してください。Rork が tsconfigPathstypedRoutes をデフォルトで true にする時期と false にする時期があり、生成時の状態によって forbidden が出やすさが変わります。

新しく Rork でプロジェクトを生成したら、まず app.jsonexpo.experiments を確認して、自分のオフライン運用方針と合うかをチェックする習慣をおすすめします。実体験として、これを最初にやるかどうかでオフライン環境でのトラブル発生頻度がはっきり変わります。

次に試すこと

expo start --offline での起動が安定したら、次の検証ポイントは「オフラインで開発しているときの Hot Reload の挙動」と「Metro バンドラのキャッシュ管理」です。.expo/cache/ を消すべきタイミングを知っておくと、長期出張先での開発がさらに安定します。同じ問題に取り組んでいる方の参考になれば嬉しいです。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-03-26
Rork の React Native ビルドエラーを切り分ける — Metro・Gradle・Xcode・Expo
Rork で生成した React Native アプリのビルドが通らないとき、どこから疑うか。Metro Bundler・ネイティブモジュールのリンク・Gradle・Xcode・Expo 設定の順に、症状から原因へ辿る診断フローをまとめました。
開発ツール2026-05-24
Rork アプリでバックグラウンド復帰時に画面が真っ白/状態が消える原因の切り分け
Rork で作ったアプリをバックグラウンドに置いたまま数時間放置して戻ると、画面が真っ白になったり、編集途中のデータが消えていたり、再ログインを求められたりする。AppState・AsyncStorage 復元タイミング・iOS のメモリ回収・Navigation state 復元の4つの観点から切り分ける手順を、5,000万DL の壁紙・癒し系アプリを個人開発してきた経験を交えてまとめます。
開発ツール2026-05-20
iOS の 0x8badf00d ウォッチドッグ強制終了に Rork アプリが落ちるときの対処
Rork で作った iOS アプリが起動直後に消える。クラッシュログに 0x8badf00d。Apple のウォッチドッグが React Native の重い初期化を切ったときの正しい直し方を、私の運用中アプリで実際に効いた手順で説明します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →