Skip to content

Fix TaskParameterTaskItem.ToString() returning type name instead of item-spec - #14095

Merged
JanProvaznik merged 4 commits into
dotnet:mainfrom
huulinhnguyen-dev:dev/huulinhnguyen/fix-taskparameteritem-tostring
Jun 19, 2026
Merged

Fix TaskParameterTaskItem.ToString() returning type name instead of item-spec#14095
JanProvaznik merged 4 commits into
dotnet:mainfrom
huulinhnguyen-dev:dev/huulinhnguyen/fix-taskparameteritem-tostring

Conversation

@huulinhnguyen-dev

@huulinhnguyen-dev huulinhnguyen-dev commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Fix TaskParameterTaskItem.ToString() returning type name instead of item-spec

Fixes #13896

Context

When building xunit with a freshly built MSBuild using the /mt (multithreaded)
flag, the build fails with:

Could not find input reference assembly 'Microsoft.Build.BackEnd.TaskParameter+TaskParameterTaskItem'

The same build succeeds without /mt.

TaskParameterTaskItem is the internal wrapper MSBuild uses to marshal ITaskItem instances across node/thread boundaries. It did not override ToString(), so it fell back to object.ToString() and returned its full .NET type name
(Microsoft.Build.BackEnd.TaskParameter+TaskParameterTaskItem) instead of the item-spec. Every other ITaskItem implementation (ProjectItemInstance.TaskItem, Utilities.TaskItem, TaskItemData) overrides ToString() to return the item-spec.

This only surfaces under /mt: non-thread-safe tasks are routed to a TaskHost for isolation (TaskRouter.NeedsTaskHostInMultiThreadedModeAssemblyTaskFactoryTaskHostTask), so task outputs come back wrapped as TaskParameterTaskItem (TaskHostTask.cs:641). When a downstream task builds a path via item.ToString() — here the third-party AnnotateReferenceAssemblies task from TunnelVisionLabs.ReferenceAssemblyAnnotator, used by xunit — it gets the type name instead of the path and fails. Without /mt, the same tasks run in-process via TaskExecutionHost and receive native ProjectItemInstance.TaskItem objects (correct ToString()), so the build succeeds.

This is a long-standing latent bug; it only became visible now because /mt marshals task parameters broadly. Most tasks use item.ItemSpec, which is always correct, which is why only repos that use a task calling item.ToString() (like xunit) are affected.

Changes Made

  • Added a ToString() override to TaskParameterTaskItem in src/Shared/TaskParameter.cs, returning the escaped item-spec to match ProjectItemInstance.TaskItem.ToString().

The reported /mt (sidecar TaskHost) scenario deserializes items on the engine side using the src/Shared/TaskParameter.cs copy, so the fix there fully resolves the issue. The separate src/MSBuildTaskHost/BackEnd/TaskParameter.cs copy (the legacy net35/net472 out-of-proc task host) is intentionally left unchanged to keep the scope minimal, per review.

Testing

Notes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes MSBuild’s marshaled ITaskItem wrapper (TaskParameterTaskItem) so ToString() returns the item-spec (instead of the wrapper’s type name), addressing failures that only surface when task parameters are marshaled (notably under /mt and TaskHost boundaries).

Changes:

  • Override TaskParameterTaskItem.ToString() to return the (escaped) item-spec in both the engine and TaskHost copies of TaskParameterTaskItem.
  • Add a regression test covering ToString() behavior and round-trip serialization for ITaskItem task parameters.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/Shared/TaskParameter.cs Adds TaskParameterTaskItem.ToString() override for the shared (engine) marshaled task-item wrapper.
src/MSBuildTaskHost/BackEnd/TaskParameter.cs Adds the same ToString() override for the TaskHost-side marshaled task-item wrapper.
src/Shared/UnitTests/TaskParameter_Tests.cs Adds a regression test validating ToString() and serialization round-trip behavior.

Comment thread src/Shared/TaskParameter.cs Outdated
Comment thread src/Shared/UnitTests/TaskParameter_Tests.cs

@JanProvaznik JanProvaznik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thanks for the find, few things to adjust

Comment thread src/MSBuildTaskHost/BackEnd/TaskParameter.cs Outdated
Comment thread src/Shared/TaskParameter.cs
Comment thread src/Shared/TaskParameter.cs Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment thread src/Shared/TaskParameter.cs
Comment thread src/Shared/TaskParameter.cs
Comment thread src/Shared/UnitTests/TaskParameter_Tests.cs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@huulinhnguyen-dev
huulinhnguyen-dev marked this pull request as ready for review June 19, 2026 07:38
@JanProvaznik
JanProvaznik merged commit e775a97 into dotnet:main Jun 19, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MSBuild server manual builds validation checklist

3 participants