Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 27, 2025

Fixes #11726

Context

/getItem and /getTargetResult throw an unhandled InvalidOperationException when serializing items whose item specs contain illegal path characters (e.g., compiler command line flags from ClangTidy's GetCompileCommands target).

The JSON output formatter iterates over all metadata names including built-in metadata like FullPath, Directory, etc. When GetMetadata() is called on these, it attempts path computation which fails for non-path item specs.

Changes Made

  • Wrapped metadata retrieval in JsonOutputFormatter.cs with try-catch for InvalidOperationException
  • Added TryGetMetadata and TryGetMetadataValue helper methods that return empty string on failure
  • Applied fix to all three affected methods: AddTargetResultsInJsonFormat, AddItemInstancesInJsonFormat, AddItemsInJsonFormat

Testing

Added GetTargetResultWithIllegalPathCharacters test that verifies both /getTargetResult and /getItem succeed with items containing compiler flags as item specs.

Notes

On Linux, the test shows the path-like metadata is still computed (since / is valid in paths). On Windows, these would return empty strings. The key fix is preventing the unhandled exception crash.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • rcxvsblobprodcus328.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/msbuild/msbuild/artifacts/bin/bootstrap/core/dotnet dotnet test src/MSBuild.UnitTests/Microsoft.Build.CommandLine.UnitTests.csproj --filter FullyQualifiedName~GetTargetResultWithIllegalPathCharacters --no-build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>[Unhandled Exception]: /getItem and /getTargetResult fail for target GetCompileCommands</issue_title>
<issue_description>### Issue Description

There is an uncaught exception when trying to access certain information from the GetCompileCommands target (from ClangTidy), in particular /getTargetResult:GetCompileCommands and /getTargetResult:GetCompileCommands

Steps to Reproduce

tidytest.zip

Run either of the following commands (You could also run with target /t:ClangTidy for the same result)

msbuild tidytest.vcxproj /t:GetCompileCommands /getTargetResult:GetCompileCommands
msbuild tidytest.vcxproj /t:GetCompileCommands /getItem:CompileCommands

I expect to get a json formatted target result or item.

Actual Behavior

I get the following error when building

C:\Users\rp0656\source\repos\tidytest>msbuild tidytest.vcxproj /t:GetCompileCommands /getTargetResult:GetCompileCommands
MSBUILD : error MSB1025: An internal failure occurred while running MSBuild.
System.InvalidOperationException: The item metadata "%(FullPath)" cannot be applied to the path "/c /nologo /W3 /WX- /diagnostics:column /Od /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /EHsc /RTC1 /MDd /GS /fp:precise /permissive- /Fa"tidytest\x64\Debug\\" /Fo"tidytest\x64\Debug\\" /Gd --target=amd64-pc-windows-msvc   /TP". Illegal characters in path.
   at Microsoft.Build.Shared.ErrorUtilities.ThrowInvalidOperation(String resourceName, Object[] args)
   at Microsoft.Build.Shared.FileUtilities.ItemSpecModifiers.GetItemSpecModifier(String currentDirectory, String itemSpec, String definingProjectEscaped, String modifier, String& fullPath)
   at Microsoft.Build.Evaluation.BuiltInMetadata.GetMetadataValueEscaped(String currentDirectory, String evaluatedIncludeBeforeWildcardExpansionEscaped, String evaluatedIncludeEscaped, String definingProjectEscaped, String name, String& fullPath)
   at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetBuiltInMetadataEscaped(String name)
   at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadataEscaped(String metadataName)
   at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadata(String metadataName)
   at Microsoft.Build.CommandLine.JsonOutputFormatter.AddTargetResultsInJsonFormat(String[] targetNames, BuildResult result)
   at Microsoft.Build.CommandLine.MSBuildApp.OutputBuildInformationInJson(BuildResult result, String[] getProperty, String[] getItem, String[] getTargetResult, ILogger[] loggers, ExitType exitType, TextWriter outputStream)
   at Microsoft.Build.CommandLine.MSBuildApp.Execute(String commandLine)

Unhandled Exception: System.InvalidOperationException: The item metadata "%(FullPath)" cannot be applied to the path "/c /nologo /W3 /WX- /diagnostics:column /Od /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /EHsc /RTC1 /MDd /GS /fp:precise /permissive- /Fa"tidytest\x64\Debug\\" /Fo"tidytest\x64\Debug\\" /Gd --target=amd64-pc-windows-msvc   /TP". Illegal characters in path.
   at Microsoft.Build.Shared.ErrorUtilities.ThrowInvalidOperation(String resourceName, Object[] args)
   at Microsoft.Build.Shared.FileUtilities.ItemSpecModifiers.GetItemSpecModifier(String currentDirectory, String itemSpec, String definingProjectEscaped, String modifier, String& fullPath)
   at Microsoft.Build.Evaluation.BuiltInMetadata.GetMetadataValueEscaped(String currentDirectory, String evaluatedIncludeBeforeWildcardExpansionEscaped, String evaluatedIncludeEscaped, String definingProjectEscaped, String name, String& fullPath)
   at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetBuiltInMetadataEscaped(String name)
   at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadataEscaped(String metadataName)
   at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadata(String metadataName)
   at Microsoft.Build.CommandLine.JsonOutputFormatter.AddTargetResultsInJsonFormat(String[] targetNames, BuildResult result)
   at Microsoft.Build.CommandLine.MSBuildApp.OutputBuildInformationInJson(BuildResult result, String[] getProperty, String[] getItem, String[] getTargetResult, ILogger[] loggers, ExitType exitType, TextWriter outputStream)
   at Microsoft.Build.CommandLine.MSBuildApp.Execute(String commandLine)
   at Microsoft.Build.CommandLine.MSBuildApp.Main()

Analysis

The error suggests that it is trying to interpret the flags of the compile commands as a path, which causes an error when it can't be resolved. The function %(FullPath) is used, though it is not clear to me exactly where, but my best guess is it used on a variable that is supposed to just be the path to cl, but has been extended with flags.

See the clang tidy targets file at something similar to C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.Cpp.ClangTidy.targets

Versions & Co...


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@dotnet-policy-service
Copy link
Contributor

Hello @@copilot, I noticed that you’re changing an .swr file or any file under src/Package/MSBuild.VSSetup.. Please make sure to validate this change by an experimental VS insertion. This is accomplished by pushing to an exp/* branch, which requires write permissions to this repo.

Copilot AI and others added 2 commits November 27, 2025 14:04
…egal path characters

Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com>
…ilt-in modifier'

Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix unhandled exception for GetCompileCommands target Fix unhandled exception in /getItem and /getTargetResult for items with illegal path characters Nov 27, 2025
Copilot AI requested a review from JanProvaznik November 27, 2025 14:12
@JanProvaznik
Copy link
Member

JanProvaznik commented Nov 27, 2025

PS C:\Users\janprovaznik\Downloads\tidytest> D:\msbuilds\msb9\artifacts\bin\bootstrap\net472\MSBuild\Current\Bin\amd64\MSBuild.exe tidytest.vcxproj /t:GetCompileCommands /getItem:CompileCommands
{
  "Items": {
    "CompileCommands": [
      {
        "Identity": "/c /nologo /W3 /WX- /diagnostics:column /Od /Oy- /D WIN32 /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /EHsc /RTC1 /MDd /GS /fp:precise /permissive- /Fa\u0022tidytest\\Debug\\\\\u0022 /Fo\u0022tidytest\\Debug\\\\\u0022 /Gd --target=i686-pc-windows-msvc   /TP",
        "WorkingDirectory": "C:\\Users\\janprovaznik\\Downloads\\tidytest",
        "Files": "C:\\Users\\janprovaznik\\Downloads\\tidytest\\main.cpp",
        "ToolPath": "C:\\Windows\\system32\\CL.exe",
        "FullPath": "",
        "RootDir": "",
        "Filename": "",
        "Extension": "",
        "RelativeDir": "",
        "Directory": "",
        "RecursiveDir": "",
        "ModifiedTime": "",
        "CreatedTime": "",
        "AccessedTime": "",
        "DefiningProjectFullPath": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Microsoft\\VC\\v170\\Microsoft.Cpp.ClangTidy.targets",
        "DefiningProjectDirectory": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Microsoft\\VC\\v170\\",
        "DefiningProjectName": "Microsoft.Cpp.ClangTidy",
        "DefiningProjectExtension": ".targets"
      }
    ]
  }
}
PS C:\Users\janprovaznik\Downloads\tidytest> D:\msbuilds\msb9\artifacts\bin\bootstrap\net472\MSBuild\Current\Bin\amd64\MSBuild.exe tidytest.vcxproj /t:GetCompileCommands /getTargetResult:GetCompileCommands
{
  "TargetResults": {
    "GetCompileCommands": {
      "Result": "Success",
      "Items": [
        {
          "Identity": "/c /nologo /W3 /WX- /diagnostics:column /Od /Oy- /D WIN32 /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /EHsc /RTC1 /MDd /GS /fp:precise /permissive- /Fa\u0022tidytest\\Debug\\\\\u0022 /Fo\u0022tidytest\\Debug\\\\\u0022 /Gd --target=i686-pc-windows-msvc   /TP",
          "WorkingDirectory": "C:\\Users\\janprovaznik\\Downloads\\tidytest",
          "Files": "C:\\Users\\janprovaznik\\Downloads\\tidytest\\main.cpp",
          "ToolPath": "C:\\Windows\\system32\\CL.exe",
          "FullPath": "",
          "RootDir": "",
          "Filename": "",
          "Extension": "",
          "RelativeDir": "",
          "Directory": "",
          "RecursiveDir": "",
          "ModifiedTime": "",
          "CreatedTime": "",
          "AccessedTime": "",
          "DefiningProjectFullPath": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Microsoft\\VC\\v170\\Microsoft.Cpp.ClangTidy.targets",
          "DefiningProjectDirectory": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Microsoft\\VC\\v170\\",
          "DefiningProjectName": "Microsoft.Cpp.ClangTidy",
          "DefiningProjectExtension": ".targets"
        }
      ]
    }
  }
}

the command output from original issue makes sense

Copy link
Member

@JanProvaznik JanProvaznik left a comment

Choose a reason for hiding this comment

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

lgtm

@JanProvaznik JanProvaznik marked this pull request as ready for review December 1, 2025 10:29
Copilot AI review requested due to automatic review settings December 1, 2025 10:29
Copy link
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

This PR fixes an unhandled exception that occurs when using /getItem or /getTargetResult with items whose specs contain illegal path characters, such as compiler command-line flags from ClangTidy's GetCompileCommands target.

Key Changes

  • Added exception handling for InvalidOperationException when retrieving metadata that requires path computation
  • Created three helper methods (TryGetMetadata and two TryGetMetadataValue overloads) to safely retrieve metadata
  • Added regression test to verify the fix works for both /getItem and /getTargetResult switches

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/MSBuild/JsonOutputFormatter.cs Added exception handling in metadata retrieval to prevent crashes when item specs contain illegal path characters; added three helper methods to safely get metadata values
src/MSBuild.UnitTests/XMake_Tests.cs Added regression test that verifies both /getItem and /getTargetResult work correctly with items containing compiler flags as item specs

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Comment on lines +168 to +218
private static string TryGetMetadata(ITaskItem item, string metadataName)
{
try
{
return item.GetMetadata(metadataName);
}
catch (InvalidOperationException)
{
// Built-in metadata like FullPath, Directory, etc. require path computation.
// If the item spec contains illegal path characters, return empty string.
return string.Empty;
}
}

/// <summary>
/// Attempts to get metadata value from a ProjectItemInstance. If the metadata is a built-in metadata
/// (like FullPath, Directory, etc.) and the item spec contains illegal path characters,
/// this will catch the InvalidOperationException and return an empty string.
/// </summary>
private static string TryGetMetadataValue(ProjectItemInstance item, string metadataName)
{
try
{
return item.GetMetadataValue(metadataName);
}
catch (InvalidOperationException)
{
// Built-in metadata like FullPath, Directory, etc. require path computation.
// If the item spec contains illegal path characters, return empty string.
return string.Empty;
}
}

/// <summary>
/// Attempts to get metadata value from a ProjectItem. If the metadata is a built-in metadata
/// (like FullPath, Directory, etc.) and the item spec contains illegal path characters,
/// this will catch the InvalidOperationException and return an empty string.
/// </summary>
private static string TryGetMetadataValue(ProjectItem item, string metadataName)
{
try
{
return item.GetMetadataValue(metadataName);
}
catch (InvalidOperationException)
{
// Built-in metadata like FullPath, Directory, etc. require path computation.
// If the item spec contains illegal path characters, return empty string.
return string.Empty;
}
}
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider making the exception handling more specific to avoid potentially hiding unrelated errors. While GetItemSpecModifier wraps IO-related exceptions in InvalidOperationException, other code paths could also throw InvalidOperationException for different reasons.

Options to make this safer:

  1. Use an exception filter to check the message: catch (InvalidOperationException ex) when (ex.Message.Contains("cannot be applied to the path"))
  2. Add logging when exceptions are caught to aid debugging
  3. Consider proposing a more specific exception type in the underlying code to distinguish path-related errors

Note: This is a minor concern since the current fix correctly addresses the immediate issue and matches the documented behavior in the comments.

Copilot uses AI. Check for mistakes.
@baronfel baronfel added the bug label Dec 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Unhandled Exception]: /getItem and /getTargetResult fail for target GetCompileCommands

3 participants