.NET MAUI で作った iOS アプリを Firebase Crashlytics に接続すると、「This missing dSYM file is required to process crashes(クラッシュ解析に必要な dSYM ファイルが見つかりません)」という警告に悩まされがちです。この記事では、この警告がなぜ出るのか、そして .NET MAUI + iOS 特有のポイントを押さえながら、根本的な解決方法と運用ベストプラクティスを詳しく解説します。
Firebase Crashlytics の「dSYM ファイルが不足しています」警告とは?
Firebase Crashlytics は、クラッシュしたときのスタックトレース(メモリアドレスの羅列)を、人間が読めるソースコードの行番号へ変換してくれるサービスです。
しかし、Crashlytics はその変換(シンボリケーション)を行うために「dSYM ファイル」という鍵を必要とします。dSYM がアップロードされていないと、次のような警告がダッシュボードに表示され、クラッシュログが解析されません。
This missing dSYM file is required to process crashes
.NET MAUI で作った iOS アプリでも、ネイティブ AOT コンパイルされたコードが iOS 上で動くため、ネイティブアプリと同様に dSYM が必須です。
dSYM とシンボリケーションの基礎知識
まずは用語を整理しておきましょう。
| 用語 | 意味 |
|---|---|
| Crashlytics | アプリのクラッシュレポートを収集・解析し、ダッシュボードで可視化してくれる Firebase のサービス。 |
| dSYM ファイル | ビルド時に生成される「デバッグシンボル」のまとまり。メモリアドレスと関数名・ファイル名・行番号の対応表。 |
| シンボリケーション | クラッシュログに含まれるアドレス情報を、ソースコード上の場所(メソッド名や行番号)に復元する処理。 |
イメージとしては、
- クラッシュログ … 暗号文
- dSYM … 暗号を解く鍵
のような関係です。鍵(dSYM)が Firebase Crashlytics 側に届いていないと、Crashlytics は暗号文(クラッシュログ)を解読できず、「警告は出るのに中身が読めない」という状態になります。
.NET MAUI + iOS で dSYM 警告が出る典型パターン
.NET MAUI の iOS アプリの場合、次のような流れで dSYM がどこかで消えてしまうことが多いです。
| フェーズ | やるべきこと | .NET MAUI で起こりがちな問題 |
|---|---|---|
| 生成 | ビルド時に dSYM を出力する | csproj の DebugType が portable などになっていて、完全な dSYM が生成されない |
| 保持 | ビルド成果物から dSYM を消さない | CI/CD でアーカイブやクリーン処理の過程で dSYM を削除してしまう |
| アップロード | dSYM を Crashlytics に渡す | upload-symbols スクリプトが未設定・権限不足・実行条件不備で実行されていない |
つまり、
dSYM を「生成」 → 「保持」 → 「Crashlytics に渡す」
という 3 ステップのどこかで手が抜けていると、「dSYM ファイルが不足しています」警告に繋がります。以降の章では、この 3 ステップを順番に潰していきます。
.NET MAUI プロジェクトで dSYM を確実に生成する
最初のチェックポイントは、.NET MAUI プロジェクト(csproj)の設定です。Release ビルドでも完全なデバッグ情報が出るように、DebugType を full に設定します。
csproj に DebugType=full を設定する
MAUI プロジェクトの .csproj に、次のような設定を追加します。
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DebugType>full</DebugType>
</PropertyGroup>
既に DebugType が書かれている場合は、Release 構成だけ full になるように調整します。ターゲットフレームワークごとに分かれている場合は、iOS 向けのグループに書くとより安全です。
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)'=='Release|net8.0-ios'">
<DebugType>full</DebugType>
</PropertyGroup>
代表的な DebugType の違いは次のとおりです。
| 値 | 特徴 | Crashlytics での利用 |
|---|---|---|
| none | デバッグ情報を出力しない | dSYM が生成されないため不可 |
| portable | .NET 共通のポータブル PDB を出力 | ネイティブ側の dSYM が不足しがちで、シンボリケーションに不十分 |
| full | ネイティブデバッグに必要な情報を含んだ完全版 | Crashlytics での解析に最も適している |
.NET MAUI の iOS アプリは AOT コンパイルされたネイティブコードとして動作するため、ネイティブ側のシンボル情報がしっかり出ていることが重要です。
DebugSymbols や最適化との兼ね合い
Release ビルドでは最適化が有効になっており、デバッグビルドと比べてスタックトレースが多少変形します。それでも dSYM があれば Crashlytics 側がうまく復元してくれるので、
- Release ビルドでも
DebugType=full - 必要に応じて
DebugSymbolsをtrueに
とするのが安全です。
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
ここまで設定したら、一度クリーンして Release でビルドし、bin/Release 以下に dSYM が出力されているか確認します(Xcode のアーカイブ機能を使う場合は、アーカイブ内に .dSYM が含まれているかを後ほど確認します)。
Xcode 側で dSYM 出力設定と Bitcode を確認する
.NET MAUI で iOS アプリをビルドするとき、内部的には Xcode プロジェクトが生成されてビルドされています。Crashlytics の dSYM 警告を解消するには、Xcode 側の設定も確認しておきましょう。
Debug Information Format を「DWARF with dSYM File」に
Xcode で該当ターゲットを開き、
- Build Settings > Debug Information Format
を確認します。値が DWARF with dSYM File になっていることが重要です。
| 設定値 | 意味 | Crashlytics への影響 |
|---|---|---|
| DWARF | 実行ファイルに最小限のデバッグ情報のみ | Crashlytics に渡す dSYM ファイルが生成されない場合がある |
| DWARF with dSYM File | DWARF に加えて dSYM ファイルを生成 | dSYM が生成され、Crashlytics でシンボリケーション可能 |
Debug/Release 両方の構成で確認しておきましょう。特に Release だけ DWARF になっているケースに注意です。
Bitcode を無効にする
古いプロジェクトでは Bitcode が有効になっている場合がありますが、現在は非推奨であり、dSYM 生成やシンボルアップロード周りでトラブルの原因になりがちです。
- Build Settings > Build Options > Enable Bitcode を No に設定
特に Xcode のメジャーバージョンをまたいだときは、この設定が意図せず変わっていることがあるので注意してください。
Crashlytics への dSYM アップロードを自動化する
dSYM を生成できるようになったら、次はそれを Crashlytics に自動でアップロードする仕組みを整えます。最も一般的なのが、Firebase が配布している upload-symbols スクリプトを Xcode の Run Script Phase に追加する方法です。
CocoaPods で Firebase Crashlytics を導入している場合
CocoaPods を使っている場合、プロジェクト内に次のようなスクリプトが存在します。
${SRCROOT}/Pods/FirebaseCrashlytics/upload-symbols
このスクリプトを、ビルド後に実行される Run Script として登録します。
- Xcode で iOS ターゲットを選択
- Build Phases タブを開く
- + ボタンから New Run Script Phase を追加
- スクリプト欄に次を入力
"${SRCROOT}/Pods/FirebaseCrashlytics/upload-symbols" \
-gsp "${PROJECT_DIR}/GoogleService-Info.plist" \
-p ios "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"
Release ビルドでのみ dSYM をアップロードしたい場合は、次のような条件付きで実行することもできます。
if [ "${CONFIGURATION}" = "Release" ]; then
"${SRCROOT}/Pods/FirebaseCrashlytics/upload-symbols" \
-gsp "${PROJECT_DIR}/GoogleService-Info.plist" \
-p ios "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"
fi
このスクリプトが成功すると、ビルド完了時に dSYM が Crashlytics に送信されます。
実行権限エラーへの対処
スクリプト実行時に
Failed to upload dSYM
のようなエラーが出る場合、upload-symbols に実行権限が付いていないケースがあります。ターミナルで次のように実行権限を付与しておきましょう。
chmod +x "${SRCROOT}/Pods/FirebaseCrashlytics/upload-symbols"
CocoaPods を使わない MAUI iOS プロジェクトの場合
一部の .NET MAUI プロジェクトでは、CocoaPods を使わずに Firebase Crashlytics のバインディングライブラリを利用している場合があります。その場合は、Firebase CLI を使って dSYM をアップロードするのが分かりやすい方法です。
Firebase CLI で dSYM をアップロードする例
事前準備として、開発環境または CI 環境に Firebase CLI をインストールしておきます。その上で、次のようなコマンドで dSYM をアップロードします。
firebase crashlytics:symbols:upload \
--app=<iOSアプリID> \
<dSYMファイルまたはdSYMsディレクトリのパス>
ここで <iOSアプリID> は Firebase プロジェクトで確認できる iOS アプリの ID(1:xxxxxxxxxxxx:ios:yyyyyyyyyyyyyyyyyyyyyy のような形式)です。
CI/CD で運用する場合は、
- ビルドステップで
.xcarchiveを生成 - アーカイブ内の
dSYMsディレクトリを取り出す - Firebase CLI コマンドでアップロード
という流れをスクリプト化しておくと、毎回手動でアップロードする手間がなくなります。
NuGet パッケージと SDK を最新に保つ
Crashlytics 本体や、.NET MAUI 向けの Firebase バインディングライブラリも進化を続けています。古いパッケージを使っていると、
- 新しい Xcode/iOS に追随できておらず、dSYM の扱いで不具合を持っている
- upload-symbols スクリプトとの整合性が取れていない
といった問題に繋がることがあります。
定期的に次の点を確認しましょう。
- Firebase 関連の NuGet パッケージ(Crashlytics、Analytics など)が最新か
- .NET SDK(.NET 7 / 8 等)がサポート期間内の最新パッチレベルか
- Xcode および Command Line Tools が、サポートされている組み合わせになっているか
開発チームで「Xcode と .NET SDK のサポートバージョン表」を作っておくと、環境差異によるトラブルを減らせます。
dSYM を手動でアップロードする手順(最終手段)
自動アップロードがうまく動いていないときや、過去のビルドのクラッシュを解析したいときは、dSYM を手動でアップロードする必要があります。
Xcode から dSYM を取り出す
- Xcode を開き、メニューから Window > Organizer を選択
- 該当アプリのアーカイブ(Archives)タブを開く
- dSYM をアップロードしたいビルドを選択
- Show in Finder をクリックして .xcarchive を Finder で表示
- .xcarchive を右クリックして Show Package Contents を選択
- 中にある
dSYMsフォルダを見つけ、対象の*.app.dSYMを取り出す
この *.app.dSYM を Firebase CLI でアップロードします。
Firebase CLI でアップロードする
firebase crashlytics:symbols:upload \
--app=<iOSアプリID> \
"<path/to/MyApp.app.dSYM>"
アップロードが成功すると、Crashlytics 側で数分〜十数分程度処理が走り、そのビルドに紐づくクラッシュログが徐々に復号されていきます。
Crashlytics コンソールでアップロード状態を確認する
設定やスクリプトを変更したら、Crashlytics ダッシュボードで dSYM の状態を必ず確認しましょう。
- Firebase コンソールで対象プロジェクトを開く
- Crashlytics を選択
- 右上の設定(歯車アイコン)から Debug symbol(もしくは類似のメニュー)を開く
ビルドごとに、次のようなステータスが表示されます。
| ステータス | 意味 | 次にやること |
|---|---|---|
| Missing | dSYM が見つかっていない | 生成設定とアップロードスクリプトを確認する |
| Processing | dSYM を受け取り処理中 | 数分待ってからクラッシュレポートを再確認 |
| Complete | dSYM が利用可能で、シンボリケーション済み | クラッシュログが行番号付きで閲覧可能 |
自動アップロードがうまく動いていれば、新しいビルドが Complete になるまでがスムーズに流れるはずです。
よくあるつまずきポイントと対処法
実際に .NET MAUI + Crashlytics を運用していると、次のようなトラブルに遭遇しがちです。
| 症状 | 主な原因 | 対処方法 |
|---|---|---|
| dSYM がそもそも生成されない | DebugType が portable や none になっている | DebugType=full を Release 向けに設定し、再ビルドする |
| upload-symbols 実行時に Failed to upload dSYM | upload-symbols に実行権限がない、またはネットワーク制限 | chmod +x で実行権限を付与し、プロキシやファイアウォールも確認する |
| dSYM アップロードは成功しているのに警告が消えない | 別バージョン/別ビルド番号の dSYM をアップロードしている | ビルド番号(CFBundleVersion)と Firebase 上のビルドが一致しているか確認 |
| 複数アーキテクチャ混在でアップロードに失敗 | 古い Xcode でビルドしており、dSYM のフォーマットが新仕様と合わない | Xcode と Command Line Tools を MAUI がサポートする最新版に更新 |
| CI/CD ではクラッシュが解析されないが、ローカルビルドでは問題なし | CI スクリプトで dSYM を削除したり、upload-symbols を呼び出していない | CI のビルドパイプラインに dSYM の保存とアップロード処理を追加 |
| Crashlytics にクラッシュが届いているのにスタックトレースが「アドレスの羅列」のまま | dSYM がアップロードされていないか、処理中のまま | Debug symbol 状態を確認し、必要に応じて手動で対象ビルドの dSYM を再アップロード |
上の表を眺めると分かる通り、多くのトラブルは
- csproj 設定の不足
- Xcode / CI のスクリプト設定漏れ
のどちらかに分類できます。
CI/CD(App Center・GitHub Actions・Azure DevOps)での運用のコツ
本番運用では、手元の Mac からビルドしてアプリを配布するよりも、CI/CD を使って自動ビルド・自動配布することが多くなります。その場合、Crashlytics への dSYM アップロードも CI パイプラインの中に組み込んでおくと安心です。
典型的なパイプライン構成
例えば GitHub Actions を使う場合を例にすると、次のようなステップ構成が考えられます。
- .NET MAUI の iOS ビルド(Release)
- Xcode アーカイブの生成(
xcodebuild archive) - アーカイブから dSYMs を抽出
- Firebase CLI で dSYM をアップロード
- IPA を TestFlight / App Store にアップロード
このとき、
- dSYM を アーティファクトとして保存 しておく(後からトラブルシュートに使える)
- Firebase CLI の認証情報はシークレット管理する
といった運用ルールを決めておくと安心です。
dSYM の保管ポリシーを決めておく
Crashlytics にアップロードした後も、dSYM 自体は手元またはストレージサービス等に保管しておくことをおすすめします。
- 各ビルド(ビルド番号)ごとに dSYMs を zip で固める
- CI のアーティファクトとして一定期間保管
- 必要に応じて長期保管用のストレージに移動
将来 Crashlytics 側で問題が起きた場合でも、dSYM さえ残っていれば別ツールでシンボリケーションし直す可能性が残ります。
今後同じ警告を出さないためのチェックリスト
最後に、.NET MAUI + Firebase Crashlytics で「dSYM ファイルが不足しています」警告を出さないためのポイントをまとめます。
| 項目 | チェック内容 |
|---|---|
| csproj 設定 | DebugType=full と DebugSymbols=true が Release 構成の iOS 向けに設定されているか |
| Xcode 設定 | Debug Information Format が「DWARF with dSYM File」、Bitcode が無効になっているか |
| 自動アップロード | upload-symbols スクリプトまたは Firebase CLI を用いた dSYM アップロード処理がビルド後に必ず実行されるか |
| パッケージ更新 | Firebase 関連 NuGet パッケージと .NET SDK、Xcode がサポート範囲内の最新版か |
| 運用ルール | dSYM の保存ポリシー(どこに・どのくらい保管するか)がチーム内で共有されているか |
このチェックリストをプロジェクトの README や社内 Wiki にまとめておけば、新しいメンバーが参加したときや環境を移行するときにもスムーズに引き継ぎができます。
まとめ:dSYM はクラッシュ解析の「鍵」、3 ステップを押さえれば怖くない
Firebase Crashlytics の「dSYM ファイルが不足しています」警告は、一見すると何をどうすればよいのか分かりづらいメッセージです。しかし整理してみると、やるべきことはシンプルです。
- 生成: .NET MAUI プロジェクトで
DebugType=fullを設定し、Xcode で「DWARF with dSYM File」を選ぶ - 保持: CI/CD の途中で dSYM を削除しないようにし、必要に応じてアーティファクトとして保管する
- アップロード: upload-symbols スクリプトや Firebase CLI で Crashlytics に確実に渡す
この 3 ステップさえ守っておけば、Crashlytics のダッシュボードには行番号付きのクラッシュログが並び、.NET MAUI iOS アプリの品質改善サイクルを高速に回せるようになります。
今まさに「This missing dSYM file is required to process crashes」警告に悩まされている場合は、本記事の手順に沿って設定を見直してみてください。設定がハマった瞬間から、これまで読めなかったクラッシュログが一気に情報を語り始めるはずです。

コメント