RDK0010 — Assembly does not match its framework folder
Severity: warning · Command: redecker inspect
An assembly sits under lib/net45/, and it was compiled for net472. Restore hands it over anyway.
The folder name is a promise nothing verifies
Restore reads the folder, picks the nearest match for the consuming project, and copies out whatever is inside. It never opens the assembly. So the package installs, the build starts, and then:
warning MSB3274: The primary reference "Contoso.Widgets" could not be resolved because it was
built against the ".NETFramework,Version=v4.7.2" framework. This is a higher version than the
currently targeted framework ".NETFramework,Version=v4.5".Followed by a few hundred errors about types that no longer exist, in code you did not change.
The netstandard version is worse, because it fails later. A .NETFramework assembly under lib/netstandard2.0/ resolves fine on .NET Framework and then throws at run time on .NET, on whichever machine gets there first.
Differing is not the defect
This is the part that decides whether the rule is usable. A netstandard2.0 assembly in lib/net8.0/ is not a mistake — it is the ordinary way to win nearest-framework matching. A net45 build in lib/net452/ is a build reused rather than repeated. Across 4,205 packages, 75 pairings differ and work perfectly:
| Count | Folder | Assembly targets |
|---|---|---|
| 14 | netcoreapp3.1 | .NETStandard,Version=v2.0 |
| 11 | netstandard2.1 | .NETStandard,Version=v2.0 |
| 10 | net8.0 | .NETStandard,Version=v2.0 |
| 5 | net452 | .NETFramework,Version=v4.5 |
A rule that compared version numbers would report every one of them, and you would turn it off inside a day.
The question that matters is the one restore itself asks: can a project targeting this folder consume this assembly? NuGet ships that answer, so Redecker asks it rather than re-deriving the netstandard fallback chain, PCL profile contribution, and UAP's mapping to .NETCore,Version=v5.0.
Scoped to frameworks anyone still ships to
Half of every incompatible pairing found sat in a dead platform — PCL profiles, Silverlight, Windows Phone, Windows Store, MonoAndroid, Xamarin, UAP, Tizen. Their version schemes are each their own private joke: MonoAndroid403 is an OS version, uap10.0 means .NETCore,Version=v5.0, and a PCL profile is a set intersection rather than a version at all.
Those comparisons are not wrong. They are just unactionable — the tooling that would republish those packages no longer exists. Reporting them would trade a rule people fix for a rule people suppress, so the rule looks only at .NETFramework, .NETCoreApp and .NETStandard.
What it found
Scoped that way, it fires on 0.4% of the top 2,000 packages and 0.6% of Microsoft.* and System.*. Several are Microsoft's own:
| Package | Folder | Assembly targets |
|---|---|---|
System.Security.Cryptography.OpenSsl@5.0.0 | lib/net461/ | .NETFramework,Version=v4.7 |
Microsoft.VisualStudio.TextTemplating.15.0 | lib/net45/ | .NETFramework,Version=v4.7.2 |
Microsoft.Web.Administration@11.1.0 | lib/netstandard1.5/ | .NETFramework,Version=v4.5 |
Microsoft.CodeCoverage@18.8.1 | lib/net8.0/ | .NETFramework,Version=v4.0 |
Microsoft.VisualStudio.DesignTools.Extensibility | lib/net45/ | .NETStandard,Version=v2.0 |
That last one is the trap in reverse: netstandard2.0 needs net461 or later, so a net45 project cannot load it either. Being older is not automatically safe.
Bundled assemblies count too
Microsoft.CodeCoverage is not shipping its own broken build — the offending file is a shim it bundles. It is still reported, because the folder is a promise about everything inside it, and a consumer who cannot load the file does not care who compiled it. The finding says which case it is, because that changes who has to fix it.
Why a warning
Microsoft.CodeCoverage ships this deliberately, and it is installed in a large share of the test projects in existence. A rule that failed those builds would destroy more work than it saved.
Example
warning RDK0010: lib/net461/ contains an assembly built for .NETFramework,Version=v4.7
lib/net461/System.Security.Cryptography.OpenSsl.dll declares .NETFramework,Version=v4.7, which
a project targeting net461 cannot consume. Restore does not check this — it reads the folder
name, hands over what is inside, and the failure surfaces later as an unresolved reference or a
missing type at run time. This is the package's own assembly, so the fix is in its build.
Either pack it under a folder it satisfies, or build it for net461.Assemblies it skips
Satellites and anything nested deeper than lib/<framework>/. A resource assembly has no framework of its own.
Anything with no TargetFrameworkAttribute. 379 of the 9,221 assemblies surveyed carry none — normal for builds predating .NET 4.0. There is nothing to compare, and guessing would be worse than silence.
Anything that is not a managed assembly. Native binaries do occasionally turn up under lib/.