Serialize BuildRequestConfiguration.RequestedTargets to fix solution metaproject MSB4057 in parallel builds - #14223
Conversation
In parallel/multithreaded builds a BuildRequestConfiguration is round-tripped through translation. RequestedTargets was a get-only auto-property that was never serialized, so the deserialized configuration reset it to an empty collection. SolutionProjectGenerator emits user-requested targets (e.g. Pack) into the generated .slnx.metaproj only when they are present in config.RequestedTargets. Losing them caused solution builds to fail with MSB4057 (target does not exist) under parallel/MT builds while serial builds worked. Back RequestedTargets with a serialized field and translate it in BuildRequestConfiguration.Translate. Adds a regression test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes a backend serialization bug where solution builds requesting non-default targets (for example Pack) can fail with MSB4057 in parallel/MT builds because BuildRequestConfiguration.RequestedTargets was not preserved across node-boundary translation.
Changes:
- Back
RequestedTargetswith aList<string>field and serialize it inBuildRequestConfiguration.Translate. - Add a regression unit test ensuring
RequestedTargetsround-trips through translation.
Show a summary per file
| File | Description |
|---|---|
| src/Build/BackEnd/Shared/BuildRequestConfiguration.cs | Persist requested target names across translation by backing with a field and translating it. |
| src/Build.UnitTests/BackEnd/BuildRequestConfiguration_Tests.cs | Add regression test to ensure RequestedTargets survives translation round-trip. |
Copilot's findings
- Files reviewed: 2/2 changed files
- Comments generated: 4
|
Caution agentic threat detected Design note —
This is correct for the However, it is worth noting that
|
|
Caution agentic threat detected Code Review — PR #14223 · 24/24 dimensions checked ✅Verdict: COMMENT — no blocking issues. The fix is correct, well-targeted, and the regression test directly validates the failing scenario. Confirmed findings
All other dimensions: ✅ LGTM
|
There was a problem hiding this comment.
Caution
agentic threat detected
Threat detection flagged this output in warn mode. Manual review is REQUIRED before any follow-up automation.
Review Summary
The fix is correct and minimal. RequestedTargets is now properly round-tripped through Translate, which is exactly what the IPC path required. Root-cause analysis, code change, and regression test all align cleanly.
| # | Dimension | Verdict |
|---|---|---|
| 3 | Performance & Allocation | 🟡 1 NIT |
| 4 | Test Coverage & Completeness | 🟡 2 NITs |
| 10 | Design Before Implementation | 🟡 1 pre-existing MODERATE (out of scope) |
| 16 | Idiomatic C# Patterns | 🟡 1 NIT |
✅ 20/24 dimensions clean — all findings are NIT or pre-existing gaps.
Checklist:
- Backwards compatibility: pure bug fix, no new warnings/errors
- ChangeWave: not needed — restores correct behaviour, no user-visible opt-in/opt-out needed
- Concurrency:
_requestedTargetsis effectively immutable after construction, no mutations found anywhere in the class; aliased copy-constructor reference is safe - Wire format: new field appended at end of
Translate; mixed-version nodes are prevented by version-locked handshake before any packet exchange -
TranslateForFutureUse: correct to omit_requestedTargets— that path is for project-evaluation metadata lookup, not build-request execution
Minor action items (all NIT):
- Replace
new[] { "Build", "Pack" }with["Build", "Pack"](C# 14 collection expressions) — three occurrences inTestTranslationPreservesRequestedTargets - Add
deserializedConfig.RequestedTargets.ShouldBeEmpty()to the existingTestTranslationto explicitly verify the empty-list round-trip (sinceAssert.EqualusesInternalEqualswhich does not compareRequestedTargets)
Generated by Expert Code Review (on open) for #14223 · 1.7K AIC · ⊞ 30.3K
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thanks! I addressed the three collection-expression suggestions in 4b81ddb. On the version-gating comment: |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thanks for the thorough review. Addressed the follow-ups:
|
|
/backport to vs18.9 |
|
Started backporting to |
…solution metaproject MSB4057 in parallel builds (#14227) Backport of #14223 to vs18.9 /cc @ViktorHofer --------- Co-authored-by: Viktor Hofer <7412651+ViktorHofer@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Unblocks dotnet/dotnet#7491
Summary
Fixes a bug where building a solution that requests a non-default target (e.g.
Pack) fails withMSB4057: The target "Pack" does not exist in the projectin parallel / multithreaded builds, while the same build succeeds serially.This was observed building the
dotnet/dotnetVMR (Arcade builds the solution in two phases with different__BuildPhaseglobal properties; theSolutionBuildphase requestsBuild;Pack).Root cause
BuildRequestConfiguration.RequestedTargetswas a get-only auto-property that was never serialized inTranslate. In parallel/MT builds the configuration is round-tripped through translation (even when the work appears to run in-proc on node 1), so the deserialized configuration resetRequestedTargetsto an empty collection.SolutionProjectGeneratoronly emits user-requested targets (such asPack) into the generated.slnx.metaprojwhen they are present inconfig.RequestedTargets. With an empty set,Packwas omitted from the metaproject and the build failed withMSB4057. Serial builds never serialized the configuration, so they were unaffected.Fix
Back
RequestedTargetswith aList<string>field and translate it inBuildRequestConfiguration.Translate.Validation
Reproduced end-to-end against the
dotnet/dotnetVMR (symreader). A/B with patched MSBuild deployed into the VMR SDK:SolutionBuildgeneration[]Pack-> MSB4057[Build;Pack]Pack-> build succeedsAdded regression test
TestTranslationPreservesRequestedTargets; full*TestTranslation*suite passes (56/56, net10.0 + net472).