NETSDK1045: The Current .NET SDK Does Not Support Targeting This Version
NETSDK1045 means the SDK actually selected by the failing build cannot target the framework the project resolves to. Do not immediately install another SDK, downgrade TargetFramework, or delete global.json. First prove the requested target, the SDK the failing environment selected, and why it selected that SDK.
dotnet --version, global.json, PATH, architecture and MSBuild overrides.TargetFramework/TargetFrameworks and inherited MSBuild properties before retargeting.dotnet --version
dotnet --info
dotnet --list-sdksdotnet --version tells you which SDK this invocation selected. --list-sdks tells you which SDKs are visible to that dotnet host/architecture. Compare the selected SDK with the project's target framework before changing anything. Treat --list-sdks as architecture-scoped inventory, not proof of which SDK a build selected.
30-second decision
dotnet --version show an SDK capable of your intended target?No → determine whether the SDK is missing or selection is pinned. Yes → compare the failing build context; your IDE/CI may be selecting differently.
dotnet --list-sdks include the SDK you expect?No → check installation and host architecture. Yes → it proves only that this
dotnet architecture can see the SDK; use dotnet --version in the failing invocation context to diagnose selection.global.json above the working directory/solution?Do not check only the repository root. Search the relevant ancestor chain: CLI and MSBuild can start that search from different directories.
Run the evidence commands inside that failing environment. A successful local CLI build does not prove the other environment uses the same SDK.
Step 1 — prove the effective target framework
Open the failing project and identify TargetFramework or TargetFrameworks. NETSDK1045 is about a mismatch between the target the project resolves to and the capability of the selected SDK.
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>Do not assume the value lives only in the project file. Directory.Build.props can set properties for projects below it, and repository build logic can make the effective target differ from what you first notice.
Verify: record the target framework that the failing project is intended to build. If the target itself is accidental, correct the project/build property. If it is intentional, keep it and diagnose SDK selection.
Step 2 — prove the SDK selected in the failing context
dotnet --version
dotnet --infoRun these from the same working directory and environment used by the failing build. SDK selection can depend on configuration discovered from that location. A command run from your home directory is weak evidence for a build launched from a repository or solution.
Verify: the selected SDK major/minor is compatible with the target you intend to build. If an older SDK is selected despite a newer one being installed, continue to global.json and environment overrides.
Fix #1 — find the global.json that actually controls selection
global.json can pin an SDK and control roll-forward. The important trap is location: .NET searches upward through ancestor directories. The CLI muxer starts its search from the current working directory. The MSBuild project SDK resolver starts from the solution directory when a solution exists; otherwise from the project directory, and falls back to the working directory when neither applies. Both search upward through ancestor directories. That difference can make a terminal command and an IDE/MSBuild build discover different global.json files.
global.json selects an SDK; it does not set the project's target framework. Its version is a full SDK version and rollForward controls which installed SDKs may satisfy that request. Do not change either until you know the repository's intended SDK policy.{
"sdk": {
"version": "8.0.302",
"rollForward": "latestFeature"
}
}Do not automatically delete a repository's SDK pin. It may exist to make developer and CI builds reproducible. Decide whether the pin is stale, intentional, or needs an appropriate roll-forward policy.
Verify: run dotnet --version from the same working directory as the failing CLI invocation. For an IDE/MSBuild-only failure, also verify the solution/project context because its resolver search can begin elsewhere. The selected SDK should satisfy the repository's intended policy—not merely be the newest SDK on the machine.
Fix #2 — if the required SDK is genuinely missing, install the SDK, not just the runtime
If the target is correct and no compatible SDK appears in dotnet --list-sdks, install the appropriate .NET SDK in that environment. A runtime installation is not a substitute for the SDK required to compile the project.
Verify: restart the relevant terminal/IDE if necessary, then confirm the compatible SDK appears and is selected before rebuilding.
Fix #3 — check x86/x64/Arm64 when “the SDK is installed” but invisible
dotnet --list-sdks reports SDKs visible for the architecture of the invoked dotnet. On Windows, SDK visibility depends on the architecture of the invoked dotnet; x86, x64 and Arm64 contexts can therefore expose different inventories. A build using another host architecture can miss an SDK that exists elsewhere on the same machine.
where dotnet
dotnet --info
dotnet --list-sdksOn .NET 10 and later, the CLI also supports architecture-aware listing with --arch. Do not copy that option into older SDK environments where it is unavailable.
Verify: the host architecture used by the failing build can see the intended SDK.
Fix #4 — CLI works but Visual Studio fails
Do not treat a successful terminal build as proof that Visual Studio is using an equivalent toolchain. Visual Studio version/support, its MSBuild environment, and preview-SDK settings can affect whether the target SDK is usable. If the only compatible SDK is a preview, Visual Studio may also require preview SDK usage to be enabled.
Verify: close/restart Visual Studio after SDK/configuration changes and rebuild the same solution/configuration. If CLI and IDE still disagree, capture the SDK/MSBuild environment from the failing IDE build rather than reinstalling SDKs repeatedly.
Fix #5 — remove stale PATH or MSBuildSDKPath overrides only when proven
An old direct SDK path in PATH can route the build toward older tooling. MSBuildSDKPath is even more direct: when set, MSBuild can use it instead of normal SDK resolution.
where dotnet
echo %MSBuildSDKPath%On PowerShell, inspect $env:MSBuildSDKPath. On Linux/macOS, use which -a dotnet and printenv MSBuildSDKPath. Do not delete environment variables just because they exist; determine whether your build tooling intentionally sets them.
Verify: open a fresh shell/build process, confirm the expected host and SDK selection, then rebuild.
Fix #6 — inspect Directory.Build.props and inherited target settings
If the SDK selection looks correct but NETSDK1045 still reports an unexpected target, inspect Directory.Build.props up the repository hierarchy and other imported build configuration. These files can set TargetFramework or related properties for multiple projects.
.csproj may do nothing if another imported property determines the effective target, or may create a project-specific exception that hides the repository's intended build policy.Verify: rebuild after correcting the property at its owning configuration layer and confirm the error now names the intended target—or disappears.
Fix #7 — local works, CI or Docker fails
Run the same three evidence commands inside the runner or container that fails. The host machine's SDK inventory is irrelevant when the build executes in a container image or hosted runner with a different SDK set.
dotnet --version
dotnet --info
dotnet --list-sdksThen compare the repository's global.json, CI SDK setup action/task, working directory, architecture and environment overrides. For Docker multi-stage builds, inspect the stage that actually runs restore/build/publish. The final runtime image may intentionally contain no SDK at all, so running --list-sdks there does not diagnose NETSDK1045 from an earlier build stage.
FROM .../sdk:<version> performs the build, align that SDK image with the intended target and repository SDK policy. Do not “fix” the final aspnet/runtime image by adding an SDK merely because compilation failed in another stage.Verify: the failing CI/container selects the same intended SDK policy as the validated development build, then run the exact pipeline/build target again.
Fix #8 — preview SDK installed but not selected
A preview SDK can be present without being eligible in every invocation context. global.json supports allowPrerelease, and Visual Studio's behavior also depends on whether preview SDK use is enabled. If the project intentionally targets a preview toolchain, make that intent explicit rather than relying on accidental machine state.
Verify: dotnet --version and the IDE/build environment both select the intended preview SDK before rebuilding.
What not to do
TargetFramework merely to silence NETSDK1045 unless the product really should target the older framework.Do not delete global.json before understanding why the repository pins an SDK.Do not treat dotnet --list-sdks as SDK-selection evidence. It is architecture-scoped inventory; selection must be checked with dotnet --version in the relevant invocation context.Do not confuse an installed .NET runtime with an installed .NET SDK.Do not repeatedly reinstall SDKs when dotnet --version proves an older SDK is being selected by configuration.Do not remove MSBuildSDKPath or PATH entries without checking whether build tooling intentionally owns them.Do not use a local success to dismiss a CI/IDE failure; compare the actual build environments.Do not inspect only a Docker final/runtime stage when restore/build/publish happens in an earlier SDK stage.Do not retarget to an older framework until you have confirmed that the older target is a product requirement—not merely a workaround for a missing or mis-selected SDK.Final verification — prove selection, then rebuild
dotnet --version
dotnet --info
dotnet --list-sdks
dotnet clean
dotnet buildA clean build is useful only after the selection problem is corrected. The success condition is not “a newer SDK exists somewhere”; it is that the exact failing environment selects an SDK compatible with the project's intentional target and completes the build.
Still seeing NETSDK1045?
TargetFramework/TargetFrameworksdotnet --version, dotnet --info and dotnet --list-sdks from the failing environmentglobal.json found along the relevant CLI and solution/project ancestor search paths, plus its version, rollForward and allowPrerelease policywhere dotnet/which -a dotnet and host architectureMSBuildSDKPath if setrelevant Directory.Build.propswhether failure is CLI, Visual Studio, CI or Docker onlyOfficial references
Still stuck? Ask the community
Share the exact target, selected SDK and failing environment—not only the NETSDK1045 wrapper line.
Loading community discussion…
Comments could not load here. Open ErrorHarbor Discussions on GitHub →