Race Condition in StaticWebAssets with Multi-Targeting and TypeScript Compilation
- Dominant language
- C#
- Stars
- 3.2k
- Forks
- 1.3k
- PR merge metrics
- PR metrics pending
Description
### Description
When using multi-targeting (`net8.0;net9.0`) in a Razor Class Library project that compiles TypeScript files via `Microsoft.TypeScript.MSBuild`, a race condition occurs during `dotnet build`. The `ResolveProjectStaticWebAssets` target sometimes attempts to resolve static web assets before the TypeScript compiler has finished writing the compiled `.js` files to disk, resulting in an `InvalidOperationException`.
The error only manifests when multi-targeting is enabled. With a single target framework, the build succeeds consistently.
### Reproduction Steps
1. Create a Razor Class Library project with multi-targeting:
```xml
net8.0;net9.0
```
2. Add TypeScript compilation via `Microsoft.TypeScript.MSBuild` package
3. Configure `tsconfig.json` to output compiled files to `wwwroot/js/dist`:
```json
{
"compilerOptions": {
"rootDir": "wwwroot/ts",
"outDir": "wwwroot/js/dist"
}
}
```
4. Add a TypeScript file in `wwwroot/ts/` (e.g., `test.ts`)
5. Run `dotnet build` multiple times **on Windows**
6. The error occurs non-deterministically (race condition)
**Sample repository:** https://github.com/loop8ack/Dotnet.Issue120620.Reproduction
### Expected behavior
The build should succeed consistently.
### Actual behavior
The build fails intermittently with:
```
Microsoft.NET.Sdk.StaticWebAssets.targets(679,5): Error : System.InvalidOperationException: No file exists for the asset at either location 'D:\Source\...\wwwroot\js\dist\test.js' or 'wwwroot\js\dist\test.js'.
at Microsoft.AspNetCore.StaticWebAssets.Tasks.StaticWebAsset.ResolveFile(String identity, String originalItemSpec)
at Microsoft.AspNetCore.StaticWebAssets.Tasks.DefineStaticWebAssets.ResolveFileDetails(String originalItemSpec, String identity)
at Microsoft.AspNetCore.StaticWebAssets.Tasks.DefineStaticWebAssets.Execute()
```
### Regression?
Unknown. I have not tested whether this occurs in earlier SDK versions.
### Known Workarounds
I have implemented a workaround using file-based locking to serialize access to the `ResolveProjectStaticWebAssets` target:
```xml
```
This forces sequential execution of 'ResolveProjectStaticWebAssets' across target frameworks and appears to work reliably. However:
- This is a hack that shouldn't be necessary
- It adds build time overhead
- It requires custom MSBuild task implementations
**Alternative workaround:** Remove multi-targeting (use only a single ``) - this eliminates the race condition but is not always feasible.
### Configuration
- **SDK Version:** 9.0.304
- **OS:** Windows 11 (issue does not occur under Linux)
- **Project Type:** Razor Class Library (`Microsoft.NET.Sdk.Razor`)
- **Packages:**
- `Microsoft.AspNetCore.Components.Web` (8.0.* and 9.0.* depending on framework)
- `Microsoft.TypeScript.MSBuild` 5.8.3
**Project file excerpt:**
```xml
net8.0;net9.0
```
### Other information
The issue appears to be a timing/ordering problem in the MSBuild target execution graph when multiple target frameworks are being built:
1. With multi-targeting, MSBuild builds each target framework in parallel or in rapid succession
2. The TypeScript compilation (`CompileTypeScript` target) runs as part of the build process
3. The `ResolveProjectStaticWebAssets` target attempts to enumerate and validate static web assets
4. There is insufficient dependency declaration or synchronization between these targets
5. When building multiple frameworks, `ResolveProjectStaticWebAssets` from one framework build can race with `CompileTypeScript` from another, or the file system operations are not fully synchronized
The race is confirmed by the non-deterministic nature of the failure — it does not occur on every build, only sometimes.
The race condition appears to be Windows-specific. Testing under WSL does not reproduce the issue; conversely, the file-locking workaround causes problems on WSL/Linux.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.