Skip to content

MSBuild incremental build incorrectly reuses Source Generator output files (.g.cs) after NuGet package version change #13056

@rruggiere

Description

@rruggiere

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:

  1. NuGet package version changes
  2. Building in containerized/CI environment
  3. 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-cache on restore
  • --no-incremental on build
  • -p:UseSharedCompilation=false
  • -p:Deterministic=true

Questions

  1. Is this a known issue with MSBuild incremental build and Source Generators?
  2. Should MSBuild automatically invalidate Source Generator outputs when NuGet package versions change?
  3. 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 Application layer but the transitive dependency is in Infrastructure layer
  • This creates a cross-layer reference that works in full builds but fails when stale files are reused

Steps to Reproduce

Reproduction Steps

  1. Build project successfully with PackageA version 1.0.20
  2. Change PackageA to version 1.0.19 in .csproj (change versuib)
  3. Commit and push to trigger CI/CD pipeline
  4. Run dotnet build or dotnet publish in Docker container
  5. Build fails with errors referencing stale .g.cs files

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:

  1. Detect NuGet package version changes
  2. Invalidate all Source Generator outputs that depend on changed packages
  3. Regenerate .g.cs files from scratch when package versions change

Actual Behavior

Actual Behavior

MSBuild:

  1. Reuses stale .g.cs files from previous build
  2. Incorrectly attributes third-party Source Generator files to Microsoft generators
  3. 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.cs is 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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions