You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
packages.config pins Meziantou.Analyzer 3.0.174 and Roslynator.Analyzers 4.16.1, but 80 unconditional <Analyzer Include> items across 16 first-party .csproj files still point at the previous 3.0.156 / 4.16.0 package folders. A clean checkout restores only the pinned versions, so those 80 analyzer paths do not exist and the build fails with error CS0006. A fresh clone of main cannot build. CI passes only because its NuGet cache has a prefix restore-keys fallback that restores a pre-bump packages tree.
Clone the repository into a directory with no pre-existing packages/ folder, or delete packages/ entirely.
Run nuget restore TaskMaster.sln. Only Meziantou.Analyzer.3.0.174 and Roslynator.Analyzers.4.16.1 are installed, because those are what packages.config pins.
Run the analyzer build command above.
Observe the failure.
For the CI side, inspect .github/workflows/_build-analyzers.yml and note the cache restore-keys prefix fallback.
Expected Behavior
A clean checkout restores the pinned analyzer packages and builds. <Analyzer Include> paths agree with the versions packages.config pins.
Actual Behavior
The 80 stale <Analyzer Include> paths reference package folders that a clean restore never creates, so MSBuild reports error CS0006 (metadata file not found) and exits 1.
Counted over tracked first-party project files only (git ls-files '*.csproj', 18 files):
Meziantou 3.0.156 lines : 16
Roslynator 4.16.0 lines : 64
TOTAL stale lines : 80 across 16 files
lines citing 3.0.174 / 4.16.1 : 0
The items carry no Condition attribute, so they are evaluated unconditionally and a missing file is fatal rather than skipped. PR #573 was a Dependabot group bump that correctly updated packages.config and the Condition-guarded Import / Error lines, but not these hand-authored items - they were added by issue #181 and sit under the comment <!-- Issue #181: analyzer-only references (first-party scope). -->.
Why nothing caught it. Two independent maskings:
Local verification. The analyzer, nullable, and MSTest gates were run against PR Bump the analyzers-dev-deps group with 2 updates #573 and were green. They were green because a long-lived packages/ directory holds Meziantou.Analyzer.3.0.101, 3.0.123, 3.0.156, 3.0.174, Roslynator.Analyzers.4.16.0, and 4.16.1 from historical restores, so the stale paths resolve. A clean environment has only the two pinned versions.
CI..github/workflows/_build-analyzers.yml uses key: nuget-${{ runner.os }}-${{ hashFiles('**/packages.config') }} with restore-keys: nuget-${{ runner.os }}-. When the content-hash key misses - which is exactly what a packages.config bump causes - the prefix fallback restores an older cache containing the pre-bump packages, and the stale paths resolve. Green CI on a packages.config change is therefore not evidence that a clean restore builds.
Logs / Screenshots
Attached minimal logs or screenshot
Snippet - the offending shape, QuickFiler/QuickFiler.csproj:581-586:
<!-- Issue #181: analyzer-only references (first-party scope). Severities are set to suggestion in .editorconfig so none break the nullable TreatWarningsAsErrors build. -->
<AnalyzerInclude="..\packages\Meziantou.Analyzer.3.0.156\analyzers\dotnet\roslyn5.0\cs\Meziantou.Analyzer.dll" />
<AnalyzerInclude="..\packages\Roslynator.Analyzers.4.16.0\analyzers\dotnet\roslyn4.7\cs\Roslynator.CSharp.Analyzers.dll" />
<AnalyzerInclude="..\packages\Roslynator.Analyzers.4.16.0\analyzers\dotnet\roslyn4.7\cs\Roslynator_Analyzers_Roslynator.Common.dll" />
<AnalyzerInclude="..\packages\Roslynator.Analyzers.4.16.0\analyzers\dotnet\roslyn4.7\cs\Roslynator_Analyzers_Roslynator.Core.dll" />
<AnalyzerInclude="..\packages\Roslynator.Analyzers.4.16.0\analyzers\dotnet\roslyn4.7\cs\Roslynator_Analyzers_Roslynator.CSharp.dll" />
Impact / Severity
Blocker
High
Medium
Low
Blocker for onboarding and for any clean-environment build: a new clone, a fresh CI runner with a cold cache, or a developer who clears packages/ all hit error CS0006. It is not a blocker for the current working tree or for CI as presently configured, which is precisely why it has gone unnoticed since PR #573 merged. The severity reflects that the masking is incidental and can evaporate at any time - a cache eviction is enough.
Summary
packages.configpinsMeziantou.Analyzer 3.0.174andRoslynator.Analyzers 4.16.1, but 80 unconditional<Analyzer Include>items across 16 first-party.csprojfiles still point at the previous3.0.156/4.16.0package folders. A clean checkout restores only the pinned versions, so those 80 analyzer paths do not exist and the build fails witherror CS0006. A fresh clone ofmaincannot build. CI passes only because its NuGet cache has a prefixrestore-keysfallback that restores a pre-bumppackagestree.Environment
msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=truemainatd15f9510; introduced by PR Bump the analyzers-dev-deps group with 2 updates #573 (mergedeb6f6836)Steps to Reproduce
packages/folder, or deletepackages/entirely.nuget restore TaskMaster.sln. OnlyMeziantou.Analyzer.3.0.174andRoslynator.Analyzers.4.16.1are installed, because those are whatpackages.configpins..github/workflows/_build-analyzers.ymland note the cacherestore-keysprefix fallback.Expected Behavior
A clean checkout restores the pinned analyzer packages and builds.
<Analyzer Include>paths agree with the versionspackages.configpins.Actual Behavior
The 80 stale
<Analyzer Include>paths reference package folders that a clean restore never creates, so MSBuild reportserror CS0006(metadata file not found) and exits 1.Counted over tracked first-party project files only (
git ls-files '*.csproj', 18 files):The items carry no
Conditionattribute, so they are evaluated unconditionally and a missing file is fatal rather than skipped. PR #573 was a Dependabot group bump that correctly updatedpackages.configand theCondition-guardedImport/Errorlines, but not these hand-authored items - they were added by issue #181 and sit under the comment<!-- Issue #181: analyzer-only references (first-party scope). -->.Why nothing caught it. Two independent maskings:
packages/directory holdsMeziantou.Analyzer.3.0.101,3.0.123,3.0.156,3.0.174,Roslynator.Analyzers.4.16.0, and4.16.1from historical restores, so the stale paths resolve. A clean environment has only the two pinned versions..github/workflows/_build-analyzers.ymluseskey: nuget-${{ runner.os }}-${{ hashFiles('**/packages.config') }}withrestore-keys: nuget-${{ runner.os }}-. When the content-hash key misses - which is exactly what apackages.configbump causes - the prefix fallback restores an older cache containing the pre-bump packages, and the stale paths resolve. Green CI on apackages.configchange is therefore not evidence that a clean restore builds.Logs / Screenshots
Attached minimal logs or screenshot
Snippet - the offending shape,
QuickFiler/QuickFiler.csproj:581-586:Impact / Severity
Blocker for onboarding and for any clean-environment build: a new clone, a fresh CI runner with a cold cache, or a developer who clears
packages/all hiterror CS0006. It is not a blocker for the current working tree or for CI as presently configured, which is precisely why it has gone unnoticed since PR #573 merged. The severity reflects that the masking is incidental and can evaporate at any time - a cache eviction is enough.Source
From: docs/features/potential/2026-08-23-csproj-analyzer-paths-stale-after-dependabot-bump-breaks-fresh-clone.md