macOS(Apple Silicon)で .NET MAUI 開発をしていると、dotnet workload update を実行しても「MAUI の workload / manifest バージョンが 8.0.7 のまま」で止まり、GitHub の「.NET MAUI 8.0.20(安定版)」に上げられないように見えることがあります。本記事では、このズレが起きる理由と、実際にプロジェクトを最新パッチへ更新するための現実的な手順をまとめます。
今回の症状:dotnet workload update をしても 8.0.20 にならない
前提となる状況を、できるだけ具体的に整理します。
- 環境:macOS(Apple Silicon / arm64)
- .NET SDK:8.0.204(例)
- 目的:.NET MAUI を GitHub リリースで案内されている「8.0.20(安定版)」相当へ更新したい
- 現象:
sudo dotnet workload updateを実行しても、MAUI workload の manifest 表示が 8.0.7 のままで更新されない
このとき、多くの人が次のどちらか(または両方)を疑います。
- 「どこかが 8.0.7 依存で、8.0.20 に上げられないのでは?」
- 「GitHub の MAUI リリースと、
dotnet workloadの更新は連動していないのでは?」
結論から言うと、後者(連動しないことがある)が本質で、ここを理解すると混乱が止まります。
結論:その表示は異常とは限らない(8.0.20 は “NuGet 側のパッチ”)
GitHub の「.NET MAUI 8.0.20」は、多くの場合 Microsoft.Maui.* などの NuGet パッケージ更新(パッチ)を中心に提供されます。一方、dotnet workload update が更新するのは SDK が管理するワークロード(ツール・テンプレート・packs・manifest)で、こちらは常に GitHub のリリース番号と同じ粒度で上がるとは限りません。
つまり、同じ「MAUI」という名前でも、更新対象が違います。
| 更新したい対象 | 代表例 | 主に更新する操作 | あなたの手元に入るもの |
|---|---|---|---|
| ワークロード(workload / manifest / packs / templates) | maui, android, ios, maccatalyst など | dotnet workload update | SDK が使うツール類、テンプレート、プラットフォーム packs、manifest |
| NuGet パッケージ(プロジェクト参照) | Microsoft.Maui.Controls / Microsoft.Maui.Sdk など | VS / Rider のパッケージ管理、または dotnet add package 等 | プロジェクトが参照するライブラリ本体(バグ修正・互換修正が入りやすい) |
| .NET SDK(ビルド基盤) | 8.0.204 など | SDK 自体の更新(インストーラ / Homebrew 等) | dotnet CLI / MSBuild / 対応するワークロード運用の土台 |
この分離があるため、次のような状態は普通に起きます。
- GitHub では MAUI 8.0.20 が出ている
- しかし
dotnet --info/dotnet workload listの「manifest バージョン」は 8.0.7 のまま - それでも、プロジェクトの NuGet を 8.0.20 相当へ更新すれば、アプリは 8.0.20 の修正を取り込める
まず確認するポイント:あなたが “上げたいバージョン” はどれか
「8.0.20 にしたい」という言葉が、どの層の話なのかで取るべき手順が変わります。現場で混乱が起きやすいので、ここを先に整理します。
| やりたいこと | 見るべき表示 | 更新する場所 | 最短の手段 |
|---|---|---|---|
| MAUI の不具合修正(UI/レイアウト/ハンドラなど)を取り込みたい | NuGet の Microsoft.Maui.* のバージョン | プロジェクト(csproj / Directory.Packages.props) | NuGet 更新(後述) |
| テンプレートやビルド周り、platform packs の更新を取り込みたい | dotnet workload の manifest / packs | SDK のワークロード | dotnet workload update(必要なら SDK 更新) |
| “とにかく最新の環境にしたい” | dotnet --version / インストール済み SDK 一覧 | .NET SDK | SDK 更新 → workload 更新 → NuGet 更新 |
今回の相談は、表の1行目(NuGet 側のパッチを取り込みたい)が主目的であるケースが多いです。その場合、workload 表示が 8.0.7 のままでも、プロジェクトは 8.0.20 相当に更新できます。
ワークロード更新と NuGet 更新は別物(ここが最大の混乱ポイント)
dotnet workload update がやること
dotnet workload update は、.NET SDK が管理している「workload」を更新します。workload には次のような要素が含まれます。
- テンプレート(
dotnet new mauiなど) - プラットフォーム向け packs(Android/iOS/Mac Catalyst などのビルドに必要な部品)
- それらを束ねる manifest(どのバージョンの packs を使うかの定義)
重要なのは、workload は SDK の “機能バンド(feature band)” や配信ポリシーに合わせて更新されるという点です。GitHub リリースの数字と同じ速度で増えないことがあります。
NuGet 更新がやること
一方で、GitHub の MAUI リリースで “8.0.20” として案内される内容の多くは、次のような NuGet パッケージの更新です。
Microsoft.Maui.Controls(UI / Controls)Microsoft.Maui.Graphics(描画)Microsoft.Maui.Essentials(統合されている場合もあります)- その他
Microsoft.Maui.*系の依存パッケージ
workload を更新しても、既存プロジェクトの NuGet 参照は自動で上がりません。そのため「workload update をしたのに直らない」「新規作成しても変わらない」と感じやすいのですが、実際は プロジェクト側の NuGet を更新する運用が必要です。
実務的な推奨:MAUI の “パッチ更新” はプロジェクト側で回す
現場でトラブルを減らすなら、次の運用が一番安定します。
- SDK は定期的に更新(少なくとも同じメジャー/マイナー内でパッチ適用)
- workload は SDK 更新後にまとめて更新(環境の整合性を保つ)
- MAUI のパッチは NuGet 更新で取り込む(プロジェクトごとに検証して反映)
理由は単純で、workload は「環境を作るための部品」で、NuGet は「アプリが使うライブラリ」だからです。アプリの挙動に効きやすいのは、たいてい NuGet 側の修正です。
手順:プロジェクトを 8.0.20 相当に更新する(macOS / CLI 中心)
まず現状を見える化する
作業前に、どこが “8.0.7” で、どこが “8.0.20” なのかを分けて把握します。
dotnet --info
dotnet workload list
dotnet list package --outdated
dotnet list package --outdated は、プロジェクト内の NuGet が古い場合に一覧で出るため、最初に実行すると迷いが減ります。
workload は “更新できる分だけ” 更新する
すでに実行していると思いますが、環境整備としては次の順が安全です。
sudo dotnet workload update
sudo dotnet workload repair
ここで manifest が 8.0.7 のままでも、それだけで異常とは限りません。「この SDK が参照する feed 上で、当該 feature band に対して公開されている最新がそこまで」という状態だと、update は正しく完了しても数字は動きません。
なお、workload 更新が途中で失敗する・インストールが壊れている疑いがある場合は、次のキャッシュクリアが効くことがあります(ただし “8.0.20 にならない問題” の本筋はここではありません)。
dotnet nuget locals all --clear
NuGet を更新する(ここが本丸)
MAUI の GitHub リリース番号(例:8.0.20)を取り込みたい場合は、プロジェクトの参照を更新します。方法は大きく2つです。
csproj に MauiVersion を明示する(管理をシンプルにしたい場合)
MAUI プロジェクトでは、csproj の <PropertyGroup> に MauiVersion を指定して、MAUI 関連パッケージ群のバージョンをまとめて固定できるケースがあります。
<PropertyGroup>
<UseMaui>true</UseMaui>
<MauiVersion>8.0.20</MauiVersion>
</PropertyGroup>
プロジェクト内で個別に Microsoft.Maui.* を列挙していない構成だと、これが一番ラクです。複数プロジェクトを持つソリューションでも「どの MAUI を使っているか」が読みやすくなります。
明示しているパッケージを個別に更新する(依存関係を細かく制御したい場合)
すでに csproj で PackageReference を明示している場合は、該当パッケージを更新します。
dotnet add package Microsoft.Maui.Controls --version 8.0.20
ただし MAUI は複数パッケージが連動するため、1つだけ上げると依存の整合性が崩れることがあります。可能なら、MAUI 一式を同じパッチ番号へ揃える運用が安全です。
更新後にビルドで確認する
更新が終わったら、必ずクリーンビルドで確認します。
dotnet clean
dotnet restore
dotnet build
iOS / Mac Catalyst を含む場合は、Xcode のバージョンや、同意プロンプト(初回の codesign 等)で止まることもあるため、CI だけでなくローカルでも一度通しておくのがおすすめです。
ワークロード(manifest)の “最新版” を確認する現実的な方法
「いま配信されている MAUI workload / manifest が何か」を確認したい場合、見方は2通りあります。
CLI で確認する
手元に入っているものは、次で確認できます。
dotnet workload list
ここに出る “maui” 関連の表示が、あなたの環境が参照している manifest 群と一致します。
NuGet 側の manifest パッケージで確認する
より踏み込んで確認したい場合は、NuGet Gallery で manifest 系パッケージを見ます。例として、.NET 8 の MAUI は次のような名前の manifest パッケージで管理されます。
Microsoft.NET.Sdk.Maui.Manifest-8.0.100(例)
この “manifest パッケージのバージョン” が、dotnet workload の表示(例:8.0.7)と対応するイメージです。GitHub の MAUI リリース番号(8.0.20)とは別の番号体系なので、ここが一致しないこと自体は想定内です。
| よく見る場所 | 表示例 | 何の番号か | 一致しないと困る? |
|---|---|---|---|
| GitHub の MAUI Releases | 8.0.20 | 製品側(主に NuGet パッチ) | いいえ(workload と別管理) |
dotnet workload list の manifest 表示 | 8.0.7 | SDK が使う workload manifest | いいえ(SDK と feed に依存) |
| プロジェクトの csproj / NuGet | Microsoft.Maui.* 8.0.20 | アプリが参照するライブラリ | はい(挙動に直結しやすい) |
補足:8.0.204 の “200” が意味するもの(feature band と workload の更新範囲)
.NET SDK のバージョンは、ざっくり言うと次のように読めます(例:8.0.204)。
| 見た目 | 例 | 意味(ざっくり) |
|---|---|---|
| メジャー | 8 | .NET 8 系であること |
| マイナー | 0 | 8.0 系であること |
| feature band | 200 | SDK の “世代” の区切り(8.0.100 / 8.0.200 / 8.0.300 … のように変わる) |
| パッチ | 4 | 同じ feature band 内での修正番号 |
workload はこの feature band に強く結びつくため、dotnet workload update は基本的に「いま使っている SDK の feature band の範囲で更新できるものだけ」を更新します。
- 同じ feature band(例:8.0.2xx)の中で公開されている manifest/packs が最新なら、
workload updateは “何も変わらない” ように見える - 別の feature band(例:8.0.3xx)で workload 周りが更新されているなら、SDK 自体を上げない限りは手元の workload 表示が動かないことがある
今回の「8.0.7 のまま」は、まさにこの “範囲の違い” が絡んでいるケースが多いです。ただし、アプリ側の不具合修正を取り込むだけなら、先に NuGet 更新で解決できることも多いので、目的から逆算して動くのが安全です。
なぜ連動しないのか:workload は “環境の部品”、NuGet は “アプリの部品”
workload と NuGet が分かれているのは、運用上のメリットが大きいからです。
- workload は重い:Android/iOS などプラットフォーム packs を含み、更新には容量も時間もかかる
- SDK との相性を強く受ける:workload は MSBuild やタスク群、テンプレートとセットで検証される必要がある
- NuGet は小回りが利く:ライブラリの修正をパッチとして配りやすく、プロジェクト単位で検証しやすい
そのため、実務では「workload は安定した土台として定期更新」「MAUI の細かな不具合修正は NuGet 更新で早めに取り込む」という分業が最も回しやすくなります。
よくある落とし穴(“8.0.7 のまま” が余計に紛らわしくなる原因)
グローバルに複数 SDK が入っていて、見ている SDK が違う
macOS では SDK が複数入っていることが珍しくありません。ターミナル上で意図した SDK を使っているかは、次で確認します。
dotnet --version
dotnet --list-sdks
また、リポジトリに global.json があると、その指定 SDK が優先されます。workload を更新しても、実際のビルドは別 SDK を使っていた…というケースは頻出です。
sudo で実行した dotnet と、普段の dotnet で “場所” がずれる
Homebrew / 公式インストーラ / 自前配置など、dotnet のインストール形態によっては、sudo 実行時と通常実行時で参照する場所がずれて「更新したのに反映されない」ように見えることがあります。
- 更新は root 側に入ったが、普段の dotnet は別の場所を見ている
- またはその逆(ユーザー側に入り、
sudo側には見えない)
この手の不一致が疑わしい場合は、どの dotnet を叩いているかを確認してから整理します。
which dotnet
dotnet --info
“新規作成プロジェクト” が古い=workload が古い、とは限らない
テンプレートが生成する csproj が、必ずしも最新パッチを固定しているとは限りません。新規作成後に dotnet list package --outdated を実行し、プロジェクト側で更新するのが確実です。
チェックリスト:迷ったらここだけ見ればOK
| 確認項目 | コマンド/操作 | 期待する判断 |
|---|---|---|
| 使用中の SDK はどれ? | dotnet --version / dotnet --list-sdks | 意図した 8.0.204(または狙う SDK)になっている |
| workload 更新が反映されている? | dotnet workload list | 更新は完了している(ただし manifest が 8.0.7 のままでも異常とは限らない) |
| MAUI のパッチは入っている? | dotnet list package --outdated | Microsoft.Maui.* を 8.0.20 相当に上げられる余地がある |
| 実際に更新できた? | csproj の MauiVersion / PackageReference を確認し、dotnet build | ビルドが通り、目的の修正が反映される |
よくある質問
workload の表示が 8.0.7 のままでも、MAUI 8.0.20(NuGet)に上げて問題ない?
多くのケースでは問題になりません。workload は「ビルドやテンプレートを成立させる土台」、NuGet は「アプリが参照するライブラリ」なので、パッチ番号(8.0.xx)同士の更新であれば、NuGet だけ先に上げて不具合修正を取り込む運用は一般的です。
ただし、環境によっては toolchain の噛み合わせで差分が出ることがあります。更新後は必ず 対象プラットフォーム(Android/iOS/Mac Catalyst)ごとにビルドと実機(またはシミュレータ)確認を行い、問題が出た場合は「SDK 更新 → workload 更新」で土台から揃えるのが安全です。
どうしても workload 側も新しくしたい場合は?
workload の更新範囲は SDK の feature band に引っ張られるため、最終的には SDK 自体を更新するのが近道です。チーム開発なら、次の2点をセットで運用すると事故が減ります。
global.jsonで SDK を固定(メンバーや CI の SDK ずれを防ぐ)- SDK 更新時に workload も更新(SDK と workload の組み合わせを揃える)
NuGet を更新したのに “新規作成プロジェクト” が古いままに見える
テンプレートが生成するプロジェクトは「その時点での標準形」を作るだけで、最新パッチを常に固定しているとは限りません。新規作成後も、dotnet list package --outdated を習慣にして、プロジェクト側で更新していくのが確実です。
CI では通るのにローカルで落ちる(または逆)
ほとんどは「使っている SDK / workload のずれ」か「NuGet キャッシュ差分」です。まずはローカルと CI の dotnet --info を比較し、SDK が揃っているかを確認してください。次に、dotnet nuget locals all --clear と dotnet restore をやり直すと差分が消えることがあります。
まとめ:workload update の数字に引きずられず、NuGet を更新する
dotnet workload update で表示される MAUI の manifest バージョン(例:8.0.7)と、GitHub で告知される MAUI リリース(例:8.0.20)は、同じ粒度で連動しないことがあります。アプリの挙動改善や不具合修正を取り込む目的なら、主戦場はプロジェクト側の NuGet 更新です。
workload は「環境の土台を整えるもの」、NuGet は「アプリを最新にするもの」。この役割分担で捉えると、数字のズレに振り回されず、必要な更新を最短距離で適用できます。

コメント