macOSで .NET 9 アプリを実行すると、デバッグ実行は動くのに「デバッグなし実行」では XAML が「.NET Runtime は 8.0.10 以降が必要」と怒られて起動しないことがあります。多くは .NET 8 ランタイムが古い(8.0.5 など)か、別アーキテクチャの dotnet を参照しているのが原因です。
起きている症状:デバッグ実行はOK、デバッグなし実行でXAMLが落ちる
macOS 上で .NET アプリ(特に .NET MAUI など XAML を使うアプリ)を実行したとき、次のような差が出るケースがあります。
- IDE からデバッグ実行(F5)は動く
- 「デバッグなしで実行」やターミナルからの実行だと起動しない
- エラーには「実行中の .NET Runtime は 8.0.5、8.0.10 以降が必要」といったバージョン要求が表示される
実際に dotnet --list-runtimes を確認すると、.NET 9 系は入っているのに、.NET 8 系のランタイムが古い(8.0.5 のまま)という状態になっていることがあります。
dotnet --list-runtimes
Microsoft.AspNetCore.App 8.0.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.1 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
.NET 9 アプリなのに、なぜ .NET 8 のランタイムが要求されるのか
「.NET 9 を入れているのに、なぜ .NET 8 の 8.0.10 以上が必要?」と感じますが、macOS では次のような理由で “.NET 8 の更新” が必要になることがあります。
- プロジェクトのターゲットが実は net8.0 系になっている
例:.NET 9 SDK を使っていても、<TargetFrameworks>がnet8.0-maccatalyst等のまま、ということは珍しくありません。 - 依存ライブラリ/ツールが .NET 8 の特定パッチ以上を要求している
XAML の処理系や関連ツールが、セキュリティ修正や不具合修正の入った 8.0.10 以降を前提にしていることがあります。 - デバッグ時と通常実行時で参照している dotnet が違う
IDE が使う dotnet と、ターミナル/「デバッグなし実行」で使われる dotnet が別物(別アーキテクチャや別パス)だと、バージョン差が表面化します。
最初にやるべき確認:いま実行に使われている dotnet を特定する
更新作業に入る前に、「いま起動に使われている dotnet がどれか」を押さえると、遠回りを減らせます。
| 目的 | コマンド | 見るポイント |
|---|---|---|
| dotnet の場所を確認 | which dotnet | /usr/local/share/dotnet 配下か、別の場所か |
| dotnet の詳細情報 | dotnet --info | Host のパス、OS/アーキテクチャ、インストール先 |
| ランタイム一覧 | dotnet --list-runtimes | Microsoft.NETCore.App の 8.0.x が 8.0.10 以上か |
| SDK 一覧 | dotnet --list-sdks | 8.0.x / 9.0.x の SDK がどう共存しているか |
| Mac が Intel か Apple Silicon か | uname -m | x86_64 なら Intel、arm64 なら Apple Silicon |
ポイント:Apple Silicon(M1/M2/M3)環境は、arm64 と x64(Rosetta)の .NET が同居することがあります。
which dotnetとdotnet --infoの「実体」が一致しているかが重要です。
解決策:.NET 8 を最新へ更新する(開発なら SDK を入れるのが手早い)
結論から言うと、.NET 8 を最新のパッチに更新するのが解決策です。開発用途なら、ランタイム単体よりも .NET 8 SDK をインストールするのが簡単で確実です(SDK には .NET Runtime と ASP.NET Core Runtime が含まれます)。
公式ダウンロードページ(リンク)
まずは Microsoft の公式ページから .NET 8 を入手します。
インストール手順
- 上記の「.NET 8.0 のダウンロード」ページを開き、SDK の欄を探します。
- macOS の行で、自分の Mac に合うアーキテクチャを選んでインストーラー(.pkg)をダウンロードします。
- ダウンロードした .pkg を実行し、ウィザードに従ってインストールします。
- インストール後にターミナルを開き直して、
dotnet --list-runtimesを再確認します。
Intel / Apple Silicon の選び方(早見表)
| Mac | 推奨アーキテクチャ | 理由 | 補足 |
|---|---|---|---|
| Intel Mac | x64 | Intel は x64 のみ | arm64 は選べません |
| Apple Silicon(M1/M2/M3) | arm64(推奨) | ネイティブ実行で高速・省電力 | x64 を入れると Rosetta 用として共存可能 |
更新できたかの確認
エラーが「8.0.10 以降が必要」なので、Microsoft.NETCore.App が 8.0.10 以上になっていることを確認します。
dotnet --list-runtimes | grep Microsoft.NETCore.App
8.0.x が 8.0.10 以上(たとえば 8.0.22 など)になっていれば、ランタイム不足は解消できています。
「インストールしたのに 8.0.5 のまま」なときに疑うポイント
.NET 8 SDK を入れたのに dotnet --list-runtimes で 8.0.5 が出続ける場合、更新に失敗したというより、違う dotnet を見ている可能性が高いです。特に Apple Silicon で起きがちです。
Apple Silicon で x64(Rosetta)版 dotnet を参照している
Apple Silicon では、x64 版 .NET は /usr/local/share/dotnet/x64 にインストールされ、arm64 版は /usr/local/share/dotnet に入る設計です。ターミナルや IDE がどちらを使っているかで、見えるランタイムが変わります。
# どちらの dotnet を叩いているか
which dotnet
# dotnet バイナリの実体が arm64 / x86_64 どちらかを確認
file "$(which dotnet)"
もし「ターミナルは Rosetta で動いている」設定になっている場合、x64 版 dotnet が優先されることがあります。macOS 標準の「ターミナル」アプリでも、情報を見ると Rosetta 起動になっているケースがあるので確認してください。
PATH の順番が原因で古い方を拾っている
複数の dotnet が共存していると、PATH の先頭にある方が使われます。次のコマンドで PATH を確認し、意図しないパスが先に来ていないかを見ます。
echo $PATH | tr ':' '\n'
対処の方向性はシンプルで、よく使う方(通常は arm64)を先に拾うように PATH を整理します。最短で切り分けたい場合は、絶対パスで dotnet を指定して実行し、挙動が変わるかを確認すると原因が見えます。
# arm64 の dotnet を明示
/usr/local/share/dotnet/dotnet --list-runtimes
# x64 の dotnet を明示(Apple Silicon で x64 を入れている場合)
/usr/local/share/dotnet/x64/dotnet --list-runtimes
古いランタイムを整理したい場合:.NET Uninstall Tool を使う
「古い 8.0.5 を消して最新だけ残したい」という場合は、手動削除よりも .NET Uninstall Tool を検討します。SDK/Runtime を安全に削除するためのコマンドが用意されています。
ただし、他のアプリが特定のランタイムに依存していることもあるため、削除前に必ずリスト表示や dry-run(実行前確認)を行うのがおすすめです。
アンインストールの基本フロー
- .NET Uninstall Tool の概要(Microsoft Learn) を確認し、対応OSや制約を把握します。
- GitHub の releases から macOS 用の
dotnet-core-uninstall.tar.gzを入手して展開します。 dotnet-core-uninstall listで削除対象を確認し、必要なものだけ削除します。
# 例:削除できる SDK/Runtime の一覧表示
dotnet-core-uninstall list
# 例:まずは dry-run(実際には削除しない)
dotnet-core-uninstall dry-run --runtime --all-but-latest
# 例:不要な古い Runtime を削除(環境に合わせて慎重に)
dotnet-core-uninstall remove --runtime --all-but-latest
このツールは /usr/local/share/dotnet 配下の SDK/Runtime を対象にするなど制約があります。見えない場所に別の dotnet がある場合、削除しても状況が変わらないことがあるため、「どの dotnet を実行しているか」の確認が先です。
ランタイム更新でエラーは消えたのに、まだ動かない場合の切り分け
今回の会話でも「エラーは消えたが問題自体は残る」という追記がありました。ランタイム不足は解消したものの、別の要因が残っている可能性があります。
追加情報がない状態でも、実務でよく効く切り分けポイントをまとめます。
プロジェクトのターゲットフレームワークを確認する
まずは .csproj を開き、TargetFramework / TargetFrameworks を確認します。ここが net8.0 系なら、実行時に .NET 8 ランタイムが必要になるのは自然です。
<PropertyGroup>
<TargetFrameworks>net8.0-maccatalyst;net8.0-ios;net8.0-android</TargetFrameworks>
</PropertyGroup>
Release 実行でのみ落ちるなら、設定差(環境変数・リンク・最適化)を疑う
- Debug / Release で挙動が変わる:最適化、リンク、トリミング、AOT 設定などが影響することがあります。
- 作業ディレクトリが違う:相対パスで設定ファイルを読んでいると、デバッグ時は通るのに通常実行で失敗することがあります。
- 環境変数が違う:IDE 側だけ設定されている変数(APIキー、接続先、ログ設定など)があると差が出ます。
再現性のあるログを取るために、ターミナルから Release で実行して、標準出力・標準エラーをそのまま確認するのが手堅いです。
# Release でビルドして実行
dotnet run -c Release
# さらに詳細ログが欲しい場合(ビルドの診断ログ)
dotnet build -c Release -v diag
「起動はするがUIが出ない/すぐ落ちる」場合
macOS の場合、起動直後に落ちるときは Console.app のクラッシュログ(または IDE の出力)にヒントがあることが多いです。XAML 以外の例外が隠れていることもあるので、起動時ログを必ず確保してください。
よくある質問
.NET 8 SDK を入れると、.NET 9 の環境が壊れませんか?
通常、.NET はサイドバイサイドで共存できます。SDK を入れると対応するランタイムも入るため、8.0 と 9.0 の両方が入った状態は一般的です。問題になるのは「どの dotnet を使っているか」「プロジェクトがどの TargetFramework を要求しているか」です。
ランタイムだけ入れれば良いですか?
“実行するだけ” ならランタイムだけでも足りますが、開発(ビルド/デバッグ/ワークロード更新)まで行うなら SDK を入れる方が手早いです。SDK にはランタイムも含まれるため、バージョンを揃えやすいメリットがあります。
Apple Silicon で x64 と arm64 を両方入れても大丈夫?
可能です。ただし、x64 版は /usr/local/share/dotnet/x64、arm64 版は /usr/local/share/dotnet など、別の場所に入る前提です。IDE やターミナルがどちらを使うか(PATH や Rosetta 起動設定)を整理しないと、今回のように「入っているのに古いのが動く」状態になりやすい点に注意してください。
まとめ:macOS の「8.0.10 以降が必要」XAML エラーは、まず .NET 8 更新から
- XAML が「.NET Runtime 8.0.10 以降が必要」と出るなら、.NET 8 ランタイムが古い可能性が高い
- 開発用途なら .NET 8 SDK を公式ページから入れるのが最短(ランタイムも一緒に更新される)
- Apple Silicon は arm64 / x64 が共存し得るため、
which dotnetとdotnet --infoで実体を確認する - エラーが消えても問題が残る場合は、TargetFramework、Release 設定差、ログの確保から切り分ける

コメント