RORK LABEN
SDK58 — Expo SDK 58 のベータは3〜4週間と案内されています。安定版は React Native 0.88 が出たあと、とだけ書かれており、日付は公表されていません0.88RC1 — その React Native 0.88 は9月16日に rc.1 まで進みました。SDK 58 は 0.86 から 0.88 へ一気に上がるため、0.87 の片づけも同時に踏みます9/30 — Google Play のデベロッパー確認と Play Console 登録が未了のアプリは、9月30日以降の削除対象です。残り9日で、個人名義で出している方も対象になりますKEYWINDOW — 依存の自動更新でクライアントパッケージだけ先に上がると、CI は通るのに iOS の本番ビルドだけが落ちる、という報告が出ていますNEW — Expo Go がプレビューを開かなくなった日に、最初に見るところRNREPO — React Native のリポジトリが facebook/react-native から react/react-native へ移りました。リンクやスクリプトの参照先を確かめておきたいところですSDK58 — Expo SDK 58 のベータは3〜4週間と案内されています。安定版は React Native 0.88 が出たあと、とだけ書かれており、日付は公表されていません0.88RC1 — その React Native 0.88 は9月16日に rc.1 まで進みました。SDK 58 は 0.86 から 0.88 へ一気に上がるため、0.87 の片づけも同時に踏みます9/30 — Google Play のデベロッパー確認と Play Console 登録が未了のアプリは、9月30日以降の削除対象です。残り9日で、個人名義で出している方も対象になりますKEYWINDOW — 依存の自動更新でクライアントパッケージだけ先に上がると、CI は通るのに iOS の本番ビルドだけが落ちる、という報告が出ていますNEW — Expo Go がプレビューを開かなくなった日に、最初に見るところRNREPO — React Native のリポジトリが facebook/react-native から react/react-native へ移りました。リンクやスクリプトの参照先を確かめておきたいところです
記事一覧/開発ツール
開発ツール/2026-09-21中級

exit code 0 で止まるビルド — ログを黙らせていた設定と、空ファイルを通した存在チェック

eas build --local が exit code 0 but produced no further output で止まる件と、0 バイトのスタブが埋め込まれず dyld で落ちる件。どちらも原因は出力を減らす設定でした。自分のスクリプトを棚卸しする手順まで書き残します。

Rork571Expo210EAS Build19xcodebuildトラブルシューティング79iOS114

Rork で作ったアプリを GitHub へ書き出して、手元の Mac でビルドに移った方が最初に出会う種類の失敗があります。ターミナルに流れた最後の行が、これだけというものです。

error: the following command failed with exit code 0 but produced no further output

失敗コードが 0 という一行を前にして、私はしばらく画面を眺めておりました。0 は慣例として成功を指します。その 0 が error という語と並んでいるのですから、どちらを信じればよいのか分からなくなります。

同じ週に、もう一つ似た報告が並んでいました。ビルド自体は通るのに、実機に入れて起動した瞬間に落ちる、というものです。どちらも原因はコードの中ではなく、ビルドを進めるための小さな設定の側にありました。

exit code 0 は「成功」ではなく「何も言えませんでした」の印です

ひとつめは、Expo SDK 57 / React Native 0.86 という安定版の構成で、Xcode 27 のもとで eas build --platform ios --local を走らせたときの報告です。expo-modules-jsi の xcframework を組み立てる段で、先ほどの一行だけを残して止まります(expo/expo#50311)。

報告者が突き止めた原因は、その段で呼ばれる xcodebuild-quiet が渡されていたことでした。-quiet は警告と進捗を抑えるための指定ですが、抑える対象に実際のエラー出力まで含まれてしまいます。外側の仕組みから見ると、子プロセスは何も言わずに終わったように見えます。だから「コマンドは失敗したが、それ以上の出力は生まれなかった」という、あの奇妙な文面になるのです。

-quiet を外して回し直すと、握りつぶされていた行がそのまま出てきて、修正後は App Store Connect への提出まで通ったと書かれています。

読者の皆さまに最初にお伝えしたいのは、この一行が出たときに疑う順番です。コードを疑う前に、その段で出力を減らしている設定があるかどうかを先に見ます。順番を逆にすると、存在しないバグを半日探すことになります。

手元で確かめるときは、静かなままログだけを残す形にしておくと後が楽になります。

# 失敗の再現時だけ -quiet を外し、出力は捨てずにファイルへ逃がす
# tee を挟むので画面にも流れ、あとから grep もできます
set -o pipefail   # xcodebuild の終了コードを tee で握りつぶさないための一行です
 
xcodebuild \
  -project ios/YourApp.xcodeproj \
  -scheme YourApp \
  -configuration Release \
  -destination 'generic/platform=iOS' \
  build 2>&1 | tee "build-$(date +%Y%m%d-%H%M%S).log"
 
echo "exit=${PIPESTATUS[0]}"   # tee ではなく xcodebuild 側の終了コードを見ます

set -o pipefail${PIPESTATUS[0]} の二つがない状態でパイプを繋ぐと、判定されるのは tee の終了コードになります。つまり、ビルドが落ちても 0 が返ります。冒頭の報告とよく似た形を、自分の手で作り出してしまうことになるのです。

もう一つの沈黙は、0 バイトのファイルを「ある」と数えた存在チェックでした

ふたつめは、実機向けの EAS ビルドで作ったアプリが、起動した瞬間に dyld のクラッシュで終わるという報告です(expo/expo#50236)。ログに出るのは次の一行です。

Library not loaded: @rpath/ExpoModulesJSI.framework/ExpoModulesJSI

報告者は三段階の調査の末に、公式のビルドスクリプト create-stub-xcframework.sh に辿り着いています。そこでは、すでにスタブが作られているかどうかを -f で確かめていました。

-f は「通常ファイルとして存在するか」だけを見ます。中身が空でも、存在していれば真です。前の回のビルドが途中で落ちて 0 バイトのファイルを残していた場合、スクリプトは「もう作ってある」と判断して作り直さず、Embed Frameworks の段でも実体のないものが素通りします。アプリは出来上がり、実機で起動した瞬間に読み込めないと言われます。

修正は、判定を -s に変えるだけでした。

# 変更前: 存在すれば通す(0 バイトでも通ってしまいます)
if [ -f "$STUB_PATH" ]; then
  echo "stub already built"; exit 0
fi
 
# 変更後: 存在し、かつ空でないときだけ通します
if [ -s "$STUB_PATH" ]; then
  echo "stub already built ($(wc -c < "$STUB_PATH") bytes)"; exit 0
fi
 
# さらに安全側へ寄せるなら、壊れた残骸を先に片づけます
if [ -f "$STUB_PATH" ] && [ ! -s "$STUB_PATH" ]; then
  echo "found a zero-byte stub, removing it"
  rm -f "$STUB_PATH"
fi

一文字の差ですが、意味はまったく違います。よく使う判定の違いを並べておきます。

判定真になる条件ビルド生成物に使うとき
-e何らかの形で存在する(ディレクトリでも真)成果物の確認には弱すぎます
-f通常ファイルとして存在する(0 バイトでも真)中断した前回の残骸を通してしまいます
-s存在し、かつサイズが 0 より大きいキャッシュ判定はここから始めます
-dディレクトリとして存在する.xcframework.app はこちらで見ます

.xcframework.app はディレクトリですから、-s では測れません。中の実体を名指しして確かめるほうが確実です。

# .xcframework はディレクトリなので、中のバイナリを直接見ます
FW="build/ExpoModulesJSI.xcframework"
BIN=$(find "$FW" -name 'ExpoModulesJSI' -type f -size +0 2>/dev/null | head -1)
 
if [ -z "$BIN" ]; then
  echo "xcframework is present but empty — rebuilding" >&2
  rm -rf "$FW"
else
  echo "ok: $BIN ($(wc -c < "$BIN") bytes)"
fi

この二件には、Bot が「再現手順が足りない」として自動的に閉じたという共通点もあります。再現手順も原因も本文に書かれているのに閉じられていますので、同じ症状で検索した方が「解決済み」と読み違えないよう、issue 番号を添えて残しておきます。

自分のスクリプトを 10 分で棚卸しする

個人開発でアプリを何本か抱えていますと、ビルドを回すたびに流れる大量の行が邪魔になり、どこかの時点で -q2>/dev/null を足したくなります。私自身、配信まわりのスクリプトにそうした指定を足したことが何度もあります。足した当日は快適ですが、半年後に原因の見えない失敗として返ってきます。

順番はこうしています。

  1. 出力を減らしている箇所を数えます。
grep -rnE -- '-quiet|(^| )-q( |$)|2>\s*/dev/null|&>\s*/dev/null|> */dev/null' \
  scripts/ ios/ .github/ 2>/dev/null
  1. 見つかった行のうち、失敗しうるコマンドに付いているものだけを残します。echowhich を黙らせるのは無害です。xcodebuildpod installgradlecodesign の類は、黙らせた瞬間に診断の手がかりを失います。

  2. 成果物の存在チェックを洗います。

grep -rnE '\[ +-f +"?\$' scripts/ ios/ 2>/dev/null
  1. 残したい沈黙には、逃がし先を作ります。画面に出さない代わりに、必ずファイルへ落とします。
LOG="/tmp/ios-build-$(date +%s).log"
if ! xcodebuild -quiet ... build > "$LOG" 2>&1; then
  echo "build failed. last 40 lines:" >&2
  tail -40 "$LOG" >&2          # 黙らせても、落ちたときだけは喋らせます
  exit 1
fi
  1. 最後に、0 バイトのファイルが成果物ディレクトリに残っていないかを見ます。
find ios/build -type f -size 0 2>/dev/null

この 5 手順は、ビルドが通っている日にこそ回す価値があります。壊れてから探すと、どこまでが正常だったのかが分からなくなるためです。依存そのものの版が思い込みとずれていないかは、30日で9回出た Expo のパッチのうち、自分のアプリに入っているのはどれかを確かめるに書きました。アップロードされる範囲の思い込みについては、.easignore を置くと .gitignore は読まれなくなりますが近い話になります。

出力を減らすなら、逃がし先を必ず一つ作ります

二つの報告を並べて気づいたのは、どちらも「間違ったことをした」わけではない、ということでした。-quiet は行数を減らすための正当な指定ですし、-f はファイルの存在を確かめる素直な書き方です。問題が起きたのは、減らした情報の行き先を用意していなかった一点に尽きます。

最初のうち、私はログを短くすることをそのまま改善だと考えておりました。結果は芳しくありませんでした。短くした分だけ、失敗したときに見るものが無くなっていたのです。いまは一つだけ線を引いています。

黙らせてよいのは、落ちたときに喋り直せるようにしてある箇所だけです。

この線引きは、Rork から書き出したプロジェクトに限った話ではありません。ストアへ出すまでの道のりでは、手元の Mac・CI・EAS と、ログの置き場所が何度も変わります。変わるたびに、どこへ逃がしているのかを一つ決めておく必要があります。

次にビルドを回すときは、xcodebuild を呼んでいる行を一つ開いて、失敗した場合にその出力がどこへ行くのかだけを確かめてみてください。行き先が /dev/null になっていたら、そこを /tmp のファイルに書き換えるところから始めていただければと思います。私もそこから始めました。

最後までお読みくださり、ありがとうございました。

シェア

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

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

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

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

関連記事

開発ツール2026-04-25
Rork でアプリアイコンを変更したのに反映されない時の対処法
Rork でアプリアイコンを差し替えたのに古いアイコンが残る — iOS のアイコンキャッシュ、EAS Build のビルドキャッシュ、Android のアダプティブアイコン未設定など、原因別に確実な対処法をまとめました。
開発ツール2026-05-21
RorkでビルドしたiOSアプリがTestFlightで「ITMS-90683」拒否される — Info.plistの使用目的文字列の埋め方
Rork書き出しのiOSアプリをApp Store Connectに提出した直後、メールで「ITMS-90683: Missing Purpose String in Info.plist」を受け取る現象について、原因とapp.jsonからの恒久的な修正手順を、12年間の個人開発で繰り返しハマってきた立場から具体的に説明します。
開発ツール2026-05-03
Rork書き出しiOSプロジェクトの「pod install」が止まる — Apple Silicon時代の現実的な直し方
Rorkで生成したiOSプロジェクトのpod installが失敗する原因を、Apple Silicon Mac特有のRubyアーキテクチャ問題、CocoaPodsバージョン競合、Hermes/Folly関連の落とし穴まで具体的に解説します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます