Warning NU1510: PackageReference ***.*** will not be pruned. Consider removing this package from your dependencies, as it is likely unnecessary.
I get quite a few of these warnings when doing dotnet restore when running paket 10.0.0-alpha011 on a net10.0 project.
I guess this is the result of some changes in the .NET 10 SDK, which really aren't a problem. I still want to understand why I get them, and whether we can do some changes i how Paket works to avoid these watnings.
Also mentioned in the .NET 10 issue (#4296 ):
- https://github.com/fsprojects/Paket/issues/4296#issuecomment-3536734036
- https://github.com/fsprojects/Paket/issues/4296#issuecomment-3547114583
I asked Copilot and it came up with quite a useful summary:
Copilot Answer
Here’s what’s going on with NU1510 in your scenario.
What NU1510 means
NU1510: PackageReference ***.*** will not be pruned. Consider removing this package from your dependencies, as it is likely unnecessary.
This is a NuGet / SDK warning, not a Paket warning. It is emitted during dotnet restore when:
- You have a
PackageReferencethat ends up not contributing any compile/runtime assets to the final graph (e.g., all of its assemblies are incompatible with your target framework, or it’s fully transitive-only / design-time-only), and - The restore logic decides that the package is effectively unused for the target frameworks you’re building.
In .NET SDK 10.0, NuGet has become more aggressive and explicit about pruning “unused” references from the effective graph, and it now warns you when a reference is pruned or ignored.
Why you see this with .NET 10.0 + Paket
With Paket 10.0.0-alpha011 on a net10.0 project, you’re running into a combination of:
-
New SDK behavior in .NET 10
- The .NET 10 SDK has evolved the way it:
- Evaluates compatibility (TFM support,
lib/,ref/,runtimes/folders,buildTransitive, etc.). - Prunes packages that are determined to be unused/irrelevant to the final graph.
- Evaluates compatibility (TFM support,
- The SDK/NuGet now emits
NU1510when it concludes a package is never actually used for your project’s TFMs.
- The .NET 10 SDK has evolved the way it:
-
How Paket integrates with
dotnet restore- Paket ultimately generates MSBuild items /
PackageReferenceequivalents (directly or indirectly viapaket.referencestranslation). - Some of these references might be:
- Only needed transitively (i.e., you pinned them explicitly in Paket to control versions, but the SDK sees them as redundant).
-
For older target frameworks (e.g., they only have
lib/netstandard2.0, which might be considered irrelevant or not chosen fornet10.0if better assets exist from other packages). -
Analyzers, tooling, or design-time packages that no longer contribute usable assets for
net10.0.
When
dotnet restoreprocesses the resultingPackageReferences fornet10.0, it decides some of them are not needed and warns withNU1510. - Paket ultimately generates MSBuild items /
-
Net 10.0 & evolving TFM support in packages
- Many packages today ship assets for
netstandard2.0,net6.0,net7.0, etc., but not explicitlynet10.0. - The SDK uses a TFM compatibility matrix. In .NET 10.0, some packages:
- Are considered not compatible enough to contribute meaningful assets to
net10.0, or - Are overshadowed by other, more specific assets provided by other dependencies.
- Are considered not compatible enough to contribute meaningful assets to
- Result: the package is effectively “dead weight” for this TFM, triggering
NU1510.
- Many packages today ship assets for
So, why this shows up now (compared to older SDKs)
Older SDKs:
- Either didn’t perform as strict pruning, or
- Didn’t surface this specific diagnostic (
NU1510) as a warning.
Starting with the newer .NET SDKs (10.0 in your case):
- The restore phase has stricter logic for unused or prunable references.
- That logic is now surfaced prominently via
NU1510.
Is it actually a problem?
Often, no, it’s not a functional problem:
- Your app will still build and run.
- The warning is telling you:
- “This package does not contribute anything to the build for
net10.0.” - “You can probably remove this reference, clean up your dependency graph, and things will behave the same.”
- “This package does not contribute anything to the build for
However, it’s still useful to:
- Identify packages that are truly obsolete/unnecessary.
- Catch incorrect assumptions about what packages are actually doing for your
net10.0build.
Why Paket specifically can trigger more of these
A few common Paket patterns that tend to surface more NU1510 warnings under newer SDKs:
-
Pinning transitive dependencies as direct dependencies
- In Paket you might have:
even thoughnuget A nuget B nuget CCis already brought in byAorB. - For
net10.0,Cmight end up fully unused, so NuGet raisesNU1510.
- In Paket you might have:
-
Legacy or multi-TFM workaround dependencies
- Dependencies originally added to satisfy older TFMs (like
net461,netcoreapp3.1, etc.) that are no longer relevant fornet10.0. - The SDK sees they don’t provide any viable assets and prunes them.
- Dependencies originally added to satisfy older TFMs (like
-
Packages used only for tooling / design-time / build-time where assets are ignored
- Some packages were historically used for MSBuild props/targets or design-time tooling.
- If the SDK decides their assets no longer match the current TFM or are no longer used in the standard pipeline, it can mark them unused.
What you can/should do
At the project/package level:
-
Inspect a few of the packages mentioned in
NU1510:- Check the NuGet page or
.nuspec/lib/reffolders. - See which TFMs they support and if they have any assets that make sense for
net10.0.
- Check the NuGet page or
-
If a package truly is no longer needed:
- Remove it from:
-
paket.dependencies -
paket.referencesfor that project
-
- Run
paket install/paket updateand thendotnet restoreto verify.
- Remove it from:
-
If a package is meant to be there (e.g., analyzers, build-only tools), and it’s harmless:
- You can consider:
- Suppressing
NU1510at the project level via.csproj:<PropertyGroup> <NoWarn>$(NoWarn);NU1510</NoWarn> </PropertyGroup> - Or selectively suppressing it per package (requires more fine-grained MSBuild configuration).
- Suppressing
- You can consider:
At the Paket side (what might be worth discussing in the issue):
- Detecting and optionally not emitting certain redundant
PackageReferences for target frameworks where the package has no meaningful assets. - Providing an analysis mode / diagnostics:
- “These packages appear unused for TFM
net10.0; you can likely remove them.”
- “These packages appear unused for TFM
- Documenting that:
- With newer .NET SDKs,
NU1510warnings are expected if yourpaket.referencescontains packages that are only relevant to other TFMs or are fully transitive.
- With newer .NET SDKs,
Direct answer to your question
You see NU1510 with the latest .NET 10.0 SDK because:
- The .NET 10.0 restore logic is stricter and more explicit about unused or prunable
PackageReferences. - Some packages that Paket is feeding into the project for
net10.0are not contributing any compile/runtime/build assets for that TFM. - The SDK therefore decides they won’t be pruned into the graph (i.e., effectively ignored) and warns you to remove them as likely unnecessary.
If you share a concrete example of one of the warned packages (name + its .nuspec/TFMs), I can walk through that specific case and show exactly why net10.0 considers it unused.
https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#prunepackagereference
For transitive packages, meaning dependencies of other packages or projects, the packages are not downloaded and do not appear in any of the outputs of NuGet.
...
The benefits of package pruning are two-fold:
- Performance benefits, by virtue of reducing the number of packages within a dependency graph
- Reduction of false positives by component scanners such as NuGetAudit
Pruning is particularly valuable when auditing packages with
NuGetAuditModeset to all. If you are using .NET 9, we recommend you try out pruning by settingRestoreEnablePackagePruningto true.
So a build time optimization to not download, parse and continue the dependency tree for stuff that is included anyway (all dependencies of a runtime include library, will naturally also be runtime included libraries)?
I'm not familiar with the audit stuff as to how much trouble the "false positives" are.
For a .NET10 project I got a bunch of NU1510 on, the DLLs in question were not copied to output, so its not so bad as including a ton of extra files in the final build, far as I can tell.
I guess in the context of Paket the equivalent performance optimization would also actually to be eliminate them at paket install time?
If for some framework being used says to prune the transitive dependency, then it doesn't need to be in paket.lock for that framework, don't need to care about its dependencies, doesn't need to be downloaded. Paket might warn if such a dependency was explicitly in paket.dependencies or paket.references files for such a target framework.
I still failed to understand why Paket only puts some transitive dependencies in the .resolved file and ultimately the project (not listed in .dependencies or .references). It's only adding a few of them. Maybe those 4 bool flags give some hint? https://www.nuget.org/packages/system.buffers/
System.Buffers,4.6.1,Transitive,Main,false,true,false,true
I wanted to try find a repo on an empty project with a single dependencies+references item, but in the cases I tried it never added the System.Buffers transitive, seemingly correctly leaving it to the framework.
In the case where it is necessary to manage at the paket level for multi-targets, the list is available at:
- https://github.com/microsoft/component-detection/tree/main/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages
- https://github.com/dotnet/sdk/tree/main/src/Tasks/Microsoft.NET.Build.Tasks/FrameworkPackages
Is there a list for .NET10? Neither of those repositories have .NET 10 entries, so maybe Microsoft moved the .NET 10 build stuff someplace?
Should it be the PackageOverrides.txt files under C:\Program Files\dotnet\packs once the version and frameworks is determined?
So I guess in that case paket install might want to still resolve all of these fully, but then when adding the packages into the projects (where it should be possible to determine the Sdk and TargetFramework in use?), don't include the package, and emit a Paket specific warning if the package was explicitly in paket.references that it will have no effect?
I assume .NET is only ignoring packages with a version less or equal to the framework provided one, so that if Microsoft released a package-specific fix on NuGet that can be used without updating the full SDK & runtimes?
Might be useful to try and locate exactly where the NU1510 check happens to see the conditions?
- I can confirm that DLL files are still pruned, even though NU1510 is issued.
- Adding
<NoWarn>NU1510</NoWarn>to the project file(s) (or maybeDirectory.Build.props?) removes the warning, and everything works fine without any noise. - This warning (NU1510) will only be issued related to the PrunePackageReference feature
I suggest closing this issue, unless we are going for adding NU1510 to the list of NoWarn in Paket.Restore.targets. This could for instance be done by adding this somewhere around line 126
<PropertyGroup Condition=" '$(RestoreEnablePackagePruning)' == 'true'">
<NoWarn>$(NoWarn);NU1510</NoWarn>
</PropertyGroup>
Or maybe just change line 122:
<NoWarn>$(NoWarn);NU1603;NU1604;NU1605;NU1608;NU1510</NoWarn>
Both ways work fine with my own informal test locally, though, I have no idea whether this will remove instances of this warning that actually are useful.