Summary
This incident centers on a multi‑target .NET project where a custom build script uses DotNetPublish to generate framework‑specific outputs and then produce a NuGet package. After adding net10.0 to the project’s TargetFrameworks, the build no longer produced a NuGet package. The root cause was a misunderstanding of how NuGet packing works in multi‑target projects versus how DotNetPublish behaves.
Root Cause
The failure occurred because:
DotNetPublishdoes not create NuGet packages — it only publishes compiled outputs.- The script attempted to publish each framework separately and expected NuGet packaging to happen afterward.
- Multi‑target NuGet packages must be created using
dotnet pack, not by manually merging publish folders. - The MSBuild property
OutputPackagePathwas set, but no pack step was executed, so no.nupkgwas produced. - Publishing into separate folders (
bin/Debug/net9.0,bin/Debug/net10.0) is correct — combining them into one folder is not how NuGet multi‑targeting works.
Why This Happens in Real Systems
This class of issue is common because:
- Engineers assume publishing and packing are related operations.
- Build scripts often evolve over time and accumulate incorrect assumptions.
- Multi‑targeting introduces implicit MSBuild behavior that is easy to overlook.
- NuGet packaging is metadata‑driven, not folder‑driven.
Real-World Impact
This type of failure typically results in:
- Missing NuGet packages, blocking deployments.
- Incorrect package contents, if engineers try to manually merge outputs.
- Broken downstream builds, because consumers cannot restore the expected frameworks.
- Wasted CI time, as builds succeed but artifacts are missing.
Example or Code (if necessary and relevant)
A correct multi‑target pack step looks like this:
DotNetPack("./src/abc/abc.csproj", new DotNetPackSettings {
Configuration = configuration,
MSBuildSettings = msBuildSettings,
OutputDirectory = nuGetOutputDirectory
});
And the project file should contain:
net9.0;net10.0
No manual folder merging is required.
How Senior Engineers Fix It
Experienced engineers resolve this by:
- Separating publish and pack steps — they are different operations.
- Using
dotnet pack(orDotNetPackin Cake) to generate multi‑target NuGet packages. - Ensuring the
.csprojcontains all required metadata:<TargetFrameworks><PackageId><Version><Authors>
- Avoiding manual manipulation of output folders.
- Validating the final
.nupkgusingnuget inspectordotnet nuget verify.
Why Juniors Miss It
Less‑experienced developers often overlook this because:
DotNetPublishsounds like it should produce a package.- Multi‑targeting behavior is implicit, not obvious.
- NuGet packaging is metadata‑driven, not based on folder structure.
- Build scripts can hide the distinction between publishing and packing.
- They may assume that “multiple publish outputs” must be merged manually.
This is a classic example of how understanding MSBuild’s mental model is essential for reliable automation.