msbuild icon indicating copy to clipboard operation
msbuild copied to clipboard

Fix unhandled exception in /getItem and /getTargetResult for items with illegal path characters

Open Copilot opened this issue 1 month ago • 2 comments

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...

  • Fixes dotnet/msbuild#12589

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

Copilot avatar Nov 27 '25 13:11 Copilot

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

JanProvaznik avatar Nov 27 '25 14:11 JanProvaznik