-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Issue Description
Issue Summary
When a NuGet package version is changed (upgrade or rollback), MSBuild incremental build fails to regenerate Source Generator output files (.g.cs) in Docker/CI environments.
The stale .g.cs files from the previous package version are incorrectly reused, causing compilation errors due to type/namespace mismatches.
Key observation: The problem does NOT occur in Visual Studio local builds, only in Docker container builds and Azure DevOps agent builds.
Root Cause Hypothesis
MSBuild incremental build does not properly invalidate Source Generator output cache when:
- NuGet package version changes
- Building in containerized/CI environment
- Source Generator is brought as transitive dependency
Workaround
Using explicit flags to disable incremental build resolves the issue:
RUN dotnet restore SomeApp.Api.csproj --no-cache
&& dotnet build SomeApp.Api.csproj
-c Release
--no-restore
--no-incremental
-p:UseSharedCompilation=false
-p:Deterministic=true
&& dotnet publish SomeApp.Api.csproj
-c Release
-o /app/publish
--no-build
Flags that resolve the issue:
--no-cacheon restore--no-incrementalon build-p:UseSharedCompilation=false-p:Deterministic=true
Questions
- Is this a known issue with MSBuild incremental build and Source Generators?
- Should MSBuild automatically invalidate Source Generator outputs when NuGet package versions change?
- Is there a more targeted workaround than disabling incremental build entirely?
Additional Context
- The third-party Source Generator (auto-mapper) is brought as a transitive dependency through another corporate NuGet package
- The Source Generator decorates types in
Applicationlayer but the transitive dependency is inInfrastructurelayer - This creates a cross-layer reference that works in full builds but fails when stale files are reused
Steps to Reproduce
Reproduction Steps
- Build project successfully with
PackageAversion1.0.20 - Change
PackageAto version1.0.19in.csproj(change versuib) - Commit and push to trigger CI/CD pipeline
- Run
dotnet buildordotnet publishin Docker container - Build fails with errors referencing stale
.g.csfiles
Error Message
/src/SomeApp.Infrastructure/obj/Release/net8.0/Microsoft.Interop.ComInterfaceGenerator/Microsoft.Interop.VtableIndexStubGenerator/CreateSchemaCommandToCreateSchemaModelMapper.g.cs(3,31): error CS0234: The type or namespace name 'Application' does not exist in the namespace 'SomeApp' (are you missing an assembly reference?)
NOTE: I cannot share my project outside of a corporate context.
Expected Behavior
Expected Behavior
MSBuild should:
- Detect NuGet package version changes
- Invalidate all Source Generator outputs that depend on changed packages
- Regenerate
.g.csfiles from scratch when package versions change
Actual Behavior
Actual Behavior
MSBuild:
- Reuses stale
.g.csfiles from previous build - Incorrectly attributes third-party Source Generator files to Microsoft generators
- Attempts to compile incompatible generated code, causing build failures
Analysis
Analysis
Incorrect Generator Attribution
The error logs shows:
#13 [build 6/6] RUN dotnet publish SomeApp.Api.csproj -c Release -o /app/publish
#13 1.293 Determining projects to restore...
#13 4.173 Restored /src/SomeApp.Domain/SomeApp.Domain.csproj (in 1.52 sec).
#13 10.16 Restored /src/SomeApp.Application/SomeApp.Application.csproj (in 7.51 sec).
#13 15.73 Restored /src/SomeApp.Infrastructure/SomeApp.Infrastructure.csproj (in 13.09 sec).
#13 15.75 Restored /src/SomeApp.CrossCutting/SomeApp.CrossCutting.csproj (in 13.09 sec).
#13 15.75 Restored /src/SomeApp.Api/SomeApp.Api.csproj (in 13.1 sec).
#13 19.67 SomeApp.Domain -> /src/SomeApp.Domain/bin/Release/net8.0/SomeApp.Domain.dll
#13 20.46 /src/SomeApp.Infrastructure/obj/Release/net8.0/Microsoft.Interop.ComInterfaceGenerator/Microsoft.Interop.VtableIndexStubGenerator/CreateSchemaCommandToCreateSchemaModelMapper.g.cs(3,31): error CS0234: The type or namespace name 'Application' does not exist in the namespace 'SomeApp' (are you missing an assembly reference?) [/src/SomeApp.Infrastructure/SomeApp.Infrastructure.csproj]
#13 20.46 /src/SomeApp.Infrastructure/obj/Release/net8.0/Microsoft.Interop.ComInterfaceGenerator/Microsoft.Interop.VtableIndexStubGenerator/CreateSchemaCommandToCreateSchemaModelMapper.g.cs(21,69): error CS0246: The type or namespace name 'CreateSchemaCommand' could not be found (are you missing a using directive or an assembly reference?) [/src/SomeApp.Infrastructure/SomeApp.Infrastructure.csproj]
#13 20.89 /src/SomeApp.Application/Services/SchemaService.cs(21,58): error CS1061: 'CreateSchemaCommand' does not contain a definition for 'MapToCreateSchemaModel' and no accessible extension method 'MapToCreateSchemaModel' accepting a first argument of type 'CreateSchemaCommand' could be found (are you missing a using directive or an assembly reference?) [/src/SomeApp.Application/SomeApp.Application.csproj]
#13 ERROR: process "/bin/sh -c dotnet publish SomeApp.Api.csproj -c Release -o /app/publish" did not complete successfully: exit code: 1
However:
CreateSchemaCommandToCreateSchemaModelMapper.g.csis generated by a third-party Source Generator (corporate auto-mapper library)- MSBuild incorrectly categorizes this file under
Microsoft.Interop.ComInterfaceGenerator - The generator name changes between builds (sometimes appears under
Microsoft.Gen.Metrics,System.Text.RegularExpressions.Generator, etc.)
Versions & Configurations
Environment
- .NET SDK: 8.0.414 (Docker container), 8.0.x (local Windows)
- OS: Linux (Docker container on Azure DevOps) and Windows 11 (local development)
- Build tool: MSBuild via
dotnet build/dotnet publish - IDE: Visual Studio 2022/2026
- CI/CD: Azure DevOps Pipelines
Environment Difference
| Environment | Result |
|---|---|
| Visual Studio 2022/2026 (local Windows) | Works correctly |
| Docker container (Linux, Azure DevOps) | Fails with stale .g.cs files |
| Azure DevOps Windows agent (direct dotnet build) | Fails with stale .g.cs files |