Skip to content

Add retry gate for MSB3030 copy race in parallel CI builds#66440

Merged
wtgodbe merged 1 commit intodotnet:mainfrom
wtgodbe:wtgodbe/fix-copy-race
Apr 23, 2026
Merged

Add retry gate for MSB3030 copy race in parallel CI builds#66440
wtgodbe merged 1 commit intodotnet:mainfrom
wtgodbe:wtgodbe/fix-copy-race

Conversation

@wtgodbe
Copy link
Copy Markdown
Member

@wtgodbe wtgodbe commented Apr 23, 2026

Problem

Parallel CI builds (/m) race on shared project outputs. When a dependency's CopyFilesToOutputDirectory overwrites a DLL/PDB, consumer projects' _CopyFilesMarkedCopyLocal can see the source file as transiently missing and fail with MSB3030 ("Could not copy because it was not found").

The SDK's Copy task does not retry on FileNotFoundException — only on IOException. This causes ~25 flaky failures per month (Known Build Error #62807).

Fix

Adds a BeforeTargets="_CopyFilesMarkedCopyLocal" gate in eng/Workarounds.targets that waits for missing source files before the stock Copy task runs. Uses a RoslynCodeTaskFactory inline task that retries File.Exists up to 5 times with 500ms delay (2.5s max).

Only active in CI (ContinuousIntegrationBuild=true) — no overhead for local dev builds.

Root Cause (from binlog analysis)

  • Shared dependency projects (e.g. Hosting.Server.Abstractions) are evaluated 6+ times and CopyFilesToOutputDirectory runs twice
  • 180+ consumer projects concurrently read from the same bin/ output via _CopyFilesMarkedCopyLocal
  • The race window: the second CopyFilesToOutputDirectory briefly makes the file unavailable during overwrite

Proper Fix

Filed dotnet/msbuild#13599 requesting the Copy task retry on FileNotFoundException, not just IOException. Once that's fixed upstream, this workaround can be removed.

Relates to #62807

Copilot AI review requested due to automatic review settings April 23, 2026 16:55
@wtgodbe wtgodbe requested a review from a team as a code owner April 23, 2026 16:55
@github-actions github-actions Bot added the needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically label Apr 23, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a CI-only MSBuild workaround to reduce flaky MSB3030 copy failures caused by parallel builds racing on shared dependency outputs.

Changes:

  • Introduces a RoslynCodeTaskFactory inline task that waits/retries for missing source files to appear.
  • Hooks a new target BeforeTargets="_CopyFilesMarkedCopyLocal" to run the wait gate during CI builds.

Comment thread eng/Workarounds.targets
Comment thread eng/Workarounds.targets Outdated
Comment thread eng/Workarounds.targets Outdated
Comment thread eng/Workarounds.targets Outdated
Parallel builds race on shared project outputs: when a dependency's
CopyFilesToOutputDirectory overwrites a DLL/PDB, consumers running
_CopyFilesMarkedCopyLocal can see 'file not found' (MSB3030). The
SDK's Copy task does not retry on FileNotFoundException.

Add a BeforeTargets gate that waits up to 2.5s for missing source
files before the stock Copy task runs. Only active in CI builds
(ContinuousIntegrationBuild=true) to avoid overhead in local dev.

Proper fix: dotnet/msbuild#13599
Tracked as: dotnet#62807

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@wtgodbe wtgodbe force-pushed the wtgodbe/fix-copy-race branch from 7998fc8 to 86ec5e2 Compare April 23, 2026 17:12
@wtgodbe wtgodbe merged commit d3b23ff into dotnet:main Apr 23, 2026
25 checks passed
@dotnet-policy-service dotnet-policy-service Bot added this to the 11.0-preview4 milestone Apr 23, 2026
@wtgodbe wtgodbe modified the milestones: 11.0-preview4, 11.0-preview5 Apr 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants