dotnet / dotnet/msbuild

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

Open
#13,056 0 comments 0 reactions 1 assignee Claimed by @rainersigwald View on GitHub
Dominant language
C#
Stars
5.5k
Forks
1.5k
Avg merge
1d 8h
Merged PRs (30d)
141

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:
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 |

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.