sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Implicit SDK-inserted PackageReferences cause friction with NuGet LockFiles

Open vedion opened this issue 1 year ago • 10 comments

Hi,

I have a project using: <Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> and <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>

I get an auto-referenced package added to the "packages.lock.json" file:

{
  "version": 2,
  "dependencies": {
    "net8.0": {
      ...
      "Microsoft.NET.ILLink.Tasks": {
        "type": "Direct",
        "requested": "[8.0.2, )",
        "resolved": "8.0.2",
        "contentHash": "hKTrehpfVzOhAz0mreaTAZgbz0DrMEbWq4n3hAo8Ks6WdxdqQhNPvzOqn9VygKuWf1bmxPdraqzTaXriO/sn0A=="
      },      
      ...

I do not have a direct reference to "Microsoft.NET.ILLink.Tasks". It is also marked with "(A)" when doing a "dotnet list .\Client.csproj package":

Project 'Client' has the following package references
   [net8.0]: 
   Top-level Package                                     Requested        Resolved      
   > Microsoft.AspNetCore.Components.WebAssembly         8.0.2            8.0.2
   > Microsoft.AspNetCore.SignalR.Client                 8.0.2            8.0.2
   > Microsoft.Extensions.Http                           8.0.0            8.0.0
   > Microsoft.Extensions.Logging.Configuration          8.0.0            8.0.0
   > Microsoft.NET.ILLink.Tasks                    (A)   [8.0.2, )        8.0.2
   > Microsoft.NET.Sdk.WebAssembly.Pack            (A)   [8.0.2, )        8.0.2

I have a global.json file that looks like this:

{
  "sdk": {
    "version": "8.0.200",
    "rollForward": "disable"
  }
}

When running "dotnet restore --force-evaluate" it respects the SDK version in global.json and updates the packages.lock.json file to use v8.0.2 of Microsoft.NET.ILLink.Tasks:

"Microsoft.NET.ILLink.Tasks": {
  "type": "Direct",
  "requested": "[8.0.2, )",
  "resolved": "8.0.2",
  "contentHash": "hKTrehpfVzOhAz0mreaTAZgbz0DrMEbWq4n3hAo8Ks6WdxdqQhNPvzOqn9VygKuWf1bmxPdraqzTaXriO/sn0A=="
},

The Microsoft-hosted agents have v8.0.202 installed and when running "dotnet restore --locked-mode" it does not respect global.json and fails: "error NU1004: The package reference Microsoft.NET.Sdk.WebAssembly.Pack version has changed from [8.0.3, ) to [8.0.2, ).The packages lock file is inconsistent with the project dependencies so restore can't be run in locked mode. Disable the RestoreLockedMode MSBuild property or pass an explicit --force-evaluate option to run restore to update the lock file."

- task: PowerShell@2
  displayName: 'Restore NuGet packages'
  inputs:
    targetType: 'inline'
    script: |
      dotnet restore --locked-mode --configfile "$(Build.SourcesDirectory)/NuGet.config"

Best Regards, Anders Havn

Expected Behavior

"dotnet restore --locked-mode" also respects the .NET SDK version in global.json.

vedion avatar Mar 22 '24 13:03 vedion

@dotnet/illink-contrib a new issue has been filed in the ILLink area, please triage

Thanks for creating this issue! We believe this issue is related to NuGet tooling, which is maintained by the NuGet team. Thus, we closed this one and encourage you to raise this issue in the NuGet repository instead. Don’t forget to check out NuGet’s contributing guide before submitting an issue!

If you believe this issue was closed out of error, please comment to let us know.

Happy Coding!

I have now tried to create the issue in the NuGet repository instead but it was also closed and said I should create it here instead?! :/

https://github.com/NuGet/Home/issues/13344

vedion avatar Mar 22 '24 20:03 vedion

So basically we are in a dead end? NuGet blames the SDK and the SDK blames NuGet. I have lock files enabled for all my projects and my Blazor WASM project always breaks the build every time a new SDK is released because it doesn't respect the global.json.

lock file: Image

every new sdk release: Image

ricardomomm avatar Oct 15 '25 14:10 ricardomomm

I've reopened this issue to track the general friction between SDK-provided implicit PackageReferences and NuGet Lock Files.

Our current recommendation for users that want to use a lock file is to also use a global.json that pins to an exact version. If you want to lock your packages, you must also lock all components that influence package selections, which includes the SDK.

baronfel avatar Oct 15 '25 14:10 baronfel

Hi @baronfel , to add more context, I do use the global.json file, here is my setup if you want to try to reproduce:

My global.json file is pinned to the version 9.0.305 My lock file for my Blazor WASM I have Microsoft.NET.ILLink.Tasks and Microsoft.NET.Sdk.WebAssembly.Pack, both saved referencing 9.0.9 (9.0.305), My pipeline has two steps, one to install the sdk referenced in global.json (9.0.305), and another to install wasm-tools which doesn't allow specifying a version and as soon as a new SDK is launched will download the newest one, in this case (9.0.10 or 9.0.306) Next my pipeline will trigger a dotnet restore with --locked-mode

It will successfully restore all other projects dependencies and throw an error in Blazor Wasm lock file, IDK exactly what causes it, the fact that I cannot make the wasm-tool install the version I'm at, it will always download latest, or dotnet restore that doesn't not respect these two references in my lock file and try to restore the latest.

ricardomomm avatar Oct 15 '25 14:10 ricardomomm

@ricardomomm can you show a snippet or example of how your pipelines are configured? I suspect that what's happening here is that the default .NET SDK installation methods in both GitHub Actions and AzDo actually install the versions you specify to a shared root directory that is already pre-provisioned with some SDK installs - so if your global.json is not strong enough (specifically, if you do not disable roll-forward with "rollForward": "disabled") then you will roll forward onto the newer SDKs in this shared space.

If this is your scenario, I would:

  • disable roll forward in your global json
  • change your pipeline SDK installations from the default behaviors to instead install to a non-shared location

baronfel avatar Oct 15 '25 14:10 baronfel

Sure thing @baronfel , here follows the steps I mentioned from my pipeline, and my global.json, and you are right about not being strong enough probably.

Pipeline: Image

global.json { "sdk": { "version": "9.0.305" } }

Here is the log with some parts omitted:

2025-10-15T13:01:35.7315214Z ##[section]Starting: Use .NET 9 2025-10-15T13:01:35.7322751Z ============================================================================== 2025-10-15T13:01:35.7322926Z Task : Use .NET Core 2025-10-15T13:01:35.7323022Z Description : Acquires a specific version of the .NET Core SDK from the internet or the local cache and adds it to the PATH. Use this task to change the version of .NET Core used in subsequent tasks. Additionally provides proxy support. 2025-10-15T13:01:35.7323307Z Version : 2.259.1 2025-10-15T13:01:35.7323416Z Author : Microsoft Corporation 2025-10-15T13:01:35.7323537Z Help : https://aka.ms/AA4xgy0 2025-10-15T13:01:35.7323648Z ============================================================================== 2025-10-15T13:01:36.3801526Z Found version 9.0.305 in channel 9.0 for user specified version spec: 9.0.305 2025-10-15T13:01:36.4227906Z get-os-distro: Error: Distribution specific OS name and version could not be detected: UName = Linux 2025-10-15T13:01:36.4228509Z Getting URL to download .NET Core sdk version: 9.0.305. 2025-10-15T13:01:36.4229000Z Detecting OS platform to find correct download package for the OS. 2025-10-15T13:01:36.4229533Z [command]/opt/azdo2/_work/_tasks/UseDotNet_b0ce7256-7898-45d3-9cb5-176b752bfea6/2.259.1/externals/get-os-distro.sh 2025-10-15T13:01:36.4230056Z Primary:linux-x64 2025-10-15T13:01:36.4230441Z Legacy:-x64 2025-10-15T13:01:36.4230704Z Detected platform (Primary): linux-x64 2025-10-15T13:01:36.4230965Z Detected platform (Legacy): -x64 2025-10-15T13:01:36.4231237Z Version: 9.0.305 was found in cache. 2025-10-15T13:01:36.4247458Z Creating global tool path and pre-pending to PATH. 2025-10-15T13:01:36.4252293Z ##[section]Finishing: Use .NET 9 2025-10-15T13:01:36.4301624Z ##[section]Starting: Install wasm-tools 2025-10-15T13:01:36.4311287Z ============================================================================== 2025-10-15T13:01:36.4311440Z Task : .NET Core 2025-10-15T13:01:36.4311548Z Description : Build, test, package, or publish a dotnet application, or run a custom dotnet command 2025-10-15T13:01:36.4311722Z Version : 2.259.0 2025-10-15T13:01:36.4311828Z Author : Microsoft Corporation 2025-10-15T13:01:36.4311951Z Help : https://docs.microsoft.com/azure/devops/pipelines/tasks/build/dotnet-core-cli 2025-10-15T13:01:36.4312163Z ============================================================================== 2025-10-15T13:01:36.7661701Z [command]/opt/azdo2/_work/_tool/dotnet/dotnet workload install wasm-tools -s https://api.nuget.org/v3/index.json 2025-10-15T13:01:37.0248347Z 2025-10-15T13:01:37.6416514Z Workload(s) 'wasm-tools' are already installed. 2025-10-15T13:01:37.6452585Z Installing pack Microsoft.NET.Runtime.WebAssembly.Sdk version 9.0.10... 2025-10-15T13:01:37.6453441Z Pack Microsoft.NET.Runtime.WebAssembly.Sdk version 9.0.10 is already installed. 2025-10-15T13:01:37.6454071Z Writing workload pack installation record for Microsoft.NET.Runtime.WebAssembly.Sdk version 9.0.10... 2025-10-15T13:01:37.6619136Z Installing pack Microsoft.NET.Sdk.WebAssembly.Pack version 9.0.10... 2025-10-15T13:01:37.6619938Z Pack Microsoft.NET.Sdk.WebAssembly.Pack version 9.0.10 is already installed. 2025-10-15T13:01:37.6620412Z Writing workload pack installation record for Microsoft.NET.Sdk.WebAssembly.Pack version 9.0.10... 2025-10-15T13:01:37.6621598Z Installing pack Microsoft.NETCore.App.Runtime.Mono.browser-wasm version 9.0.10... 2025-10-15T13:01:37.6622028Z Pack Microsoft.NETCore.App.Runtime.Mono.browser-wasm version 9.0.10 is already installed. 2025-10-15T13:01:37.6622481Z Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.browser-wasm version 9.0.10... 2025-10-15T13:01:37.6622940Z Installing pack Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.browser-wasm version 9.0.10... 2025-10-15T13:01:37.6623420Z Pack Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.browser-wasm version 9.0.10 is already installed. 2025-10-15T13:01:37.6623906Z Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.browser-wasm version 9.0.10... 2025-10-15T13:01:37.6624567Z Installing pack Microsoft.NET.Runtime.MonoAOTCompiler.Task version 9.0.10... 2025-10-15T13:01:37.6624997Z Pack Microsoft.NET.Runtime.MonoAOTCompiler.Task version 9.0.10 is already installed. 2025-10-15T13:01:37.6625453Z Writing workload pack installation record for Microsoft.NET.Runtime.MonoAOTCompiler.Task version 9.0.10... 2025-10-15T13:01:37.6625881Z Installing pack Microsoft.NET.Runtime.MonoTargets.Sdk version 9.0.10... 2025-10-15T13:01:37.6626280Z Pack Microsoft.NET.Runtime.MonoTargets.Sdk version 9.0.10 is already installed. 2025-10-15T13:01:37.6626704Z Writing workload pack installation record for Microsoft.NET.Runtime.MonoTargets.Sdk version 9.0.10... 2025-10-15T13:01:37.6627410Z Installing pack Microsoft.NET.Runtime.Emscripten.3.1.56.Node.linux-x64 version 9.0.10... 2025-10-15T13:01:37.6627863Z Pack Microsoft.NET.Runtime.Emscripten.3.1.56.Node.linux-x64 version 9.0.10 is already installed. 2025-10-15T13:01:37.6628331Z Writing workload pack installation record for Microsoft.NET.Runtime.Emscripten.3.1.56.Node.linux-x64 version 9.0.10... 2025-10-15T13:01:37.6628806Z Installing pack Microsoft.NET.Runtime.Emscripten.3.1.56.Cache.linux-x64 version 9.0.10... 2025-10-15T13:01:37.6629240Z Pack Microsoft.NET.Runtime.Emscripten.3.1.56.Cache.linux-x64 version 9.0.10 is already installed. 2025-10-15T13:01:37.6629709Z Writing workload pack installation record for Microsoft.NET.Runtime.Emscripten.3.1.56.Cache.linux-x64 version 9.0.10... 2025-10-15T13:01:37.6630163Z Installing pack Microsoft.NET.Runtime.Emscripten.3.1.56.Sdk.linux-x64 version 9.0.10... 2025-10-15T13:01:37.6630593Z Pack Microsoft.NET.Runtime.Emscripten.3.1.56.Sdk.linux-x64 version 9.0.10 is already installed. 2025-10-15T13:01:37.6631065Z Writing workload pack installation record for Microsoft.NET.Runtime.Emscripten.3.1.56.Sdk.linux-x64 version 9.0.10... 2025-10-15T13:01:37.6940643Z Garbage collecting for SDK feature band(s) 8.0.200 8.0.300 8.0.400 9.0.200 9.0.300... 2025-10-15T13:01:37.7176183Z 2025-10-15T13:01:37.7176830Z Successfully installed workload(s) . 2025-10-15T13:01:37.7176975Z 2025-10-15T13:01:37.7571534Z 2025-10-15T13:01:37.7665849Z ##[section]Finishing: Install wasm-tools 2025-10-15T13:01:37.7708964Z ##[section]Starting: DotNet Restore 2025-10-15T13:01:37.7717578Z ============================================================================== 2025-10-15T13:01:37.7717734Z Task : .NET Core 2025-10-15T13:01:37.7717840Z Description : Build, test, package, or publish a dotnet application, or run a custom dotnet command 2025-10-15T13:01:37.7718012Z Version : 2.259.0 2025-10-15T13:01:37.7718108Z Author : Microsoft Corporation 2025-10-15T13:01:37.7718226Z Help : https://docs.microsoft.com/azure/devops/pipelines/tasks/build/dotnet-core-cli 2025-10-15T13:01:37.7718430Z ============================================================================== 2025-10-15T13:01:38.4354682Z [command]/opt/azdo2/_work/_tool/dotnet/dotnet restore /opt/azdo2/_work/1/s/.sln --packages .\Packages --configfile /opt/azdo2/_work/1/Nuget/tempNuGet_57668.config --no-cache --verbosity Normal --locked-mode 2025-10-15T13:01:38.6700196Z Build started 10/15/2025 13:01:38. 2025-10-15T13:01:38.8664662Z 1>Project "/opt/azdo2/_work/1/s/.sln" on node 1 (Restore target(s)). 2025-10-15T13:02:00.3424851Z NuGet Config files used: 2025-10-15T13:02:00.3425187Z /opt/azdo2/_work/1/Nuget/tempNuGet_57668.config 2025-10-15T13:02:00.3425489Z
2025-10-15T13:02:00.3425761Z Feeds used: 2025-10-15T13:02:00.3426069Z https://api.nuget.org/v3/index.json 2025-10-15T13:02:00.3426524Z https://
/v3/index.json 2025-10-15T13:02:00.3426891Z https://
/v3/index.json 2025-10-15T13:02:00.3427227Z /opt/azdo2/_work/_tool/dotnet/library-packs 2025-10-15T13:02:00.3435999Z
2025-10-15T13:02:00.3436270Z Installed: 2025-10-15T13:02:00.3471892Z 1>Done Building Project "/opt/azdo2/_work/1/s/
.sln" (Restore target(s)) -- FAILED. 2025-10-15T13:02:00.3707912Z 2025-10-15T13:02:00.3708726Z Build FAILED. 2025-10-15T13:02:00.3733062Z 2025-10-15T13:02:00.3734502Z "/opt/azdo2/_work/1/s/************.sln" (Restore target) (1) -> 2025-10-15T13:02:00.3735349Z (Restore target) -> 2025-10-15T13:02:00.3736890Z /opt/azdo2/_work/1/s/src/************Blazor/*************Blazor.csproj : error NU1004: The package reference Microsoft.NET.Sdk.WebAssembly.Pack version has changed from [9.0.9, ) to [9.0.10, ).The packages lock file is inconsistent with the project dependencies so restore can't be run in locked mode. Disable the RestoreLockedMode MSBuild property or pass an explicit --force-evaluate option to run restore to update the lock file. 2025-10-15T13:02:00.3738069Z 2025-10-15T13:02:00.3739001Z 0 Warning(s) 2025-10-15T13:02:00.3739433Z 1 Error(s) 2025-10-15T13:02:00.3739585Z 2025-10-15T13:02:00.3740042Z Time Elapsed 00:00:21.70 2025-10-15T13:02:00.4162259Z 2025-10-15T13:02:00.4261731Z ##[error]Error: The process '/opt/azdo2/_work/_tool/dotnet/dotnet' failed with exit code 1 2025-10-15T13:02:00.4270198Z ##[error]Packages failed to restore

ricardomomm avatar Oct 15 '25 15:10 ricardomomm

I have observed that implicit packages also get inserted when PublishSingleFile gets enabled.

  1. Create a new project, e.g. a console app with dotnet new console.
  2. Enable PublishSingleFile and RestorePackagesWithLockFile in the .csproj. As a result, the packages.lock.json looks like this:
{
  "version": 1,
  "dependencies": {
    "net8.0": {
      "Microsoft.NET.ILLink.Tasks": {
        "type": "Direct",
        "requested": "[8.0.14, )",
        "resolved": "8.0.14",
        "contentHash": "4U2fd7PexNKrK5ZqfqIcXZj9/lRRjFsLgA/pxuFQTuGQuLYP/+7yACz/j7EmWbEj/fspOf4mafi/vHIy/rKDzQ=="
      }
    }
  }
}

Pinning the dotnet sdk with rollforward false will cause friction since the dotnet sdk patch version needs to be kept in sync between development and runners.

je-hes avatar Nov 06 '25 08:11 je-hes

Same issue here: when running dotnet publish, this leads to...

Repository /home/runner/work/RaspiFanController/RaspiFanController is dirty. Please commit your changes:
ModifiedInWorkdir: RaspiFanController/packages.lock.json

...with git diff showing:

diff --git a/RaspiFanController/packages.lock.json b/RaspiFanController/packages.lock.json
index bab88e6..e881bdc 100644
--- a/RaspiFanController/packages.lock.json
+++ b/RaspiFanController/packages.lock.json
@@ -17,15 +17,15 @@
       },
       "Microsoft.AspNetCore.App.Internal.Assets": {
         "type": "Direct",
-        "requested": "[10.0.1, )",
-        "resolved": "10.0.1",
-        "contentHash": "rafnWkNfJPA0nCZ5u9bFLiIhCv+aGDWBPJMejuROFMHEpsNhTdv8Cvhv+2jIH+b5485FhndbiwOQJUBMeBa6BQ=="
+        "requested": "[10.0.0, )",
+        "resolved": "10.0.0",
+        "contentHash": "0gZrESKwnlmbE8Br8XIy3kk7Pj0++9T2Ly+A8BFYYgo5EgfqWEln26cho+l92KOaHUzclhvz314RiwE910s24g=="
       },
       "Microsoft.NET.ILLink.Tasks": {
         "type": "Direct",
-        "requested": "[10.0.1, )",
-        "resolved": "10.0.1",
-        "contentHash": "ISahzLHsHY7vrwqr2p1YWZ+gsxoBRtH7gWRDK8fDUst9pp2He0GiesaqEfeX0V8QMCJM3eNEHGGpnIcPjFo2NQ=="
+        "requested": "[10.0.0, )",
+        "resolved": "10.0.0",
+        "contentHash": "kICGrGYEzCNI3wPzfEXcwNHgTvlvVn9yJDhSdRK+oZQy4jvYH529u7O0xf5ocQKzOMjfS07+3z9PKRIjrFMJDA=="
       },
       "mu88.Shared": {
         "type": "Direct",

mu88 avatar Dec 13 '25 17:12 mu88