A compatible .NET SDK was not found. means a global.json in your folder, or in
a folder above it, asks for an SDK version this machine does not have, and its
rollForward policy does not allow a newer one. Point global.json at an
installed SDK, or relax rollForward, and every dotnet command works again.
Run dotnet --list-sdks first; it works even with the broken file. Then set
"version" to one of the SDKs it lists, or keep the version and add
"rollForward": "latestFeature".
The error
The command could not be loaded, possibly because:
* You intended to execute a .NET application:
The application '--version' does not exist or is not a managed .dll or .exe.
* You intended to execute a .NET SDK command:
A compatible .NET SDK was not found.
Requested SDK version: 8.0.100
global.json file: C:\...\g1\global.json
Installed SDKs:
Install the [8.0.100] .NET SDK or update [C:\...\g1\global.json] to match an installed SDK.
Learn about SDK resolution:
https://aka.ms/dotnet/sdk-not-found
8.0.425 [C:\Program Files\dotnet\sdk]
9.0.317 [C:\Program Files\dotnet\sdk]
10.0.100-rc.1.25451.107 [C:\Program Files\dotnet\sdk]
10.0.401 [C:\Program Files\dotnet\sdk]
Only the folder path was shortened. The list of installed SDKs goes to standard output and the rest
to standard error; this log merged the two streams, which is why the list sits at the end, below the
link. The command exits with code -2147450725.
Why it happens
Before it runs an SDK command, the dotnet host looks for a global.json in the
current folder, then in each parent folder. The sdk.version in that file is a request,
and rollForward decides how far the host may move away from it. When no installed SDK
qualifies, the host has nothing to hand the command to. It cannot tell whether
--version was an SDK command or the name of an app, so it prints both guesses; the
second one is the real cause.
The trap is the default. With no rollForward at all, a request for 8.0.100 failed exactly
like latestPatch, even with 8.0.425 installed, while a request for 8.0.400 resolved to
8.0.425. The default only moves up inside the same feature band, the hundreds of the patch number
(1xx, 4xx). This is what each policy chose for a request of 8.0.100 on a machine with SDKs 8.0.425,
9.0.317 and 10.0.401:
- no
rollForward,disableorlatestPatch: the error above latestFeature: 8.0.425latestMinor: 8.0.425latestMajor: 10.0.401
A request for 9.0.100 failed with patch and resolved to 9.0.317 with feature.
The fix
Keep the requested version and let it roll forward to the newest SDK of the same release:
{ "sdk": { "version": "8.0.100", "rollForward": "latestFeature" } }
> dotnet --version
8.0.425
Naming an installed SDK exactly works too: { "sdk": { "version": "8.0.425" } } resolved
to 8.0.425. Use latestMajor only if the repository does not care which SDK builds it; here
it jumped straight to 10.0.401. If the pin is deliberate, the other fix is the one the message names:
install an SDK from that feature band (not tested here).
How it was reproduced
An empty folder holding only a global.json, with dotnet --version run inside
it; dotnet build printed the same message with build in place of
--version, and so did a subfolder with no global.json of its own. Each
rollForward value was written into the same file in turn. .NET host 10.0.12 on Windows 11,
SDKs 8.0.425, 9.0.317, 10.0.100-rc.1.25451.107 and 10.0.401 installed.
Frequently asked
- How do I fix A compatible .NET SDK was not found?
- Run dotnet --list-sdks to see the installed SDKs, then edit the global.json named in the message: set the version to one of them, or keep the version and add "rollForward": "latestFeature". The next dotnet command picks an installed SDK.
- What is the default rollForward in global.json?
- With a version and no rollForward, the host behaved like latestPatch in testing: a request for 8.0.400 resolved to 8.0.425, but a request for 8.0.100 failed, because 8.0.425 is in the 4xx feature band, not 1xx.
- Why does dotnet --version fail when dotnet --list-sdks works?
- dotnet --list-sdks and dotnet --info ran fine with the broken global.json because they do not need an SDK to be chosen. dotnet --version, build, run and the other SDK commands do, so they all fail with the same message.
More decoded errors in the Fixes category. A
global.json that pins an SDK too old for the project ends in
NETSDK1045.