Investigate crash on `dotnet restore` in Microsoft-internal repo
Report of a crash using .NET SDK 10.0.100-rc.2:
> dotnet restore
D:\CxCache\.A\DotNetSDK.RGUCrN4KjzB55QtGl8GCWA\sdk\10.0.100-rc.2.25502.107\NuGet.RestoreEx.targets(19,5): error
'{' is an unexpected token. The expected token is '"' or '''. Line 2, position 33.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String[] args)
at System.Xml.XmlTextReaderImpl.ParseAttributes()
at System.Xml.XmlTextReaderImpl.ParseElement()
at System.Xml.XmlTextReaderImpl.ParseElementContent()
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlDocument.Load(XmlReader reader)
at Microsoft.Build.Shared.SolutionConfiguration.GetProjectConfigurations(String xmlString)
at Microsoft.Build.Shared.SolutionConfiguration..ctor(String xmlString)
at Microsoft.Build.Graph.ProjectInterpretation.GetReferences(ProjectGraphNode projectGraphNode, ProjectCollection projectCollection, ProjectInstanceFactoryFunc projec
tInstanceFactory)+MoveNext()
at Microsoft.Build.Graph.GraphBuilder.ParseReferences(ProjectGraphNode parsedProject)
at Microsoft.Build.Graph.GraphBuilder.ParseProject(ConfigurationMetadata configurationMetadata)
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at System.Lazy`1.get_Value()
at Microsoft.Build.Graph.ParallelWorkSet`2.ExecuteWorkItem()
@ericstj pointed out offline that if the second line of the XML was
<ProjectConfiguration Project={
then there'd be an unexpected { on character 33, and that almost makes sense since it's written here:
https://github.com/dotnet/msbuild/blob/4cd2425e9a787959195c6a99da7e1d7c5c44f6cb/src/Build/Construction/Solution/SolutionProjectGenerator.cs#L268-L276
But why would that WriteAttributeString decide not to quote the attribute?
I was thinking that maybe something in the process of reading/writing properties and passing around something ran afoul of escaping logic. IOW - XML wrote the quotes, but they got stripped out later. Lots of places that MSBuild tries to understand strings and strip out quotes, including places that changed between .NET 8 and 10 - so this feels like the most likely cause.
I couldn't reproduce myself by trying just a simple sln, even copy pasting the content that the internal team shared from their SLN, so there must be something unique to their environment / paths / etc. Maybe some sort of unique thing in a path, like a semi-colons and equals signs in a directory names or something evil like that.
@benwitmanmsft also hit this, and captured a binlog, which I stared at a bit and discovered this minimal repro:
❯ dotnet new sln
The template "Solution File" was created successfully.
❯ dotnet sln add .\Console1\
Project `Console1\Console1.csproj` added to the solution.
❯ msbuild -t:Restore -p:RestoreUseStaticGraphEvaluation=true -v:m
MSBuild version 18.3.0-preview-25603-04+228caa11a for .NET Framework
Determining projects to restore...
All projects are up-to-date for restore.
❯ msbuild -t:Restore -p:RestoreUseStaticGraphEvaluation=true -v:m -p:CurrentSolutionConfigurationContents=asdf
MSBuild version 18.3.0-preview-25603-04+228caa11a for .NET Framework
Determining projects to restore...
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : Data at the root level is invalid. Line 1, position 1. [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at System.Xml.XmlTextReaderImpl.Throw(Exception e) [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace() [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at System.Xml.XmlTextReaderImpl.ParseDocumentContent() [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace) [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at System.Xml.XmlDocument.Load(XmlReader reader) [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at Microsoft.Build.Shared.SolutionConfiguration.GetProjectConfigurations(String xmlString) [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at Microsoft.Build.Shared.SolutionConfiguration..ctor(String xmlString) [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at Microsoft.Build.Graph.ProjectInterpretation.<GetReferences>d__24.MoveNext() [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at Microsoft.Build.Graph.GraphBuilder.ParseReferences(ProjectGraphNode parsedProject) [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at Microsoft.Build.Graph.GraphBuilder.ParseProject(ConfigurationMetadata configurationMetadata) [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at System.Lazy`1.CreateValue() [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at System.Lazy`1.LazyInitValue() [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
C:\Program Files\Microsoft Visual Studio\18\Preview\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.RestoreEx.targets(19,5): error : at Microsoft.Build.Graph.ParallelWorkSet`2.ExecuteWorkItem() [S:\repro\dotnet\msbuild\issues\12732\12732.sln]
The problem occurs when there's a global property for CurrentSolutionConfigurationContents.
So it looks like this hits in the confusing (and fortunately rare) situation where a solution is restored inside an environment that looks like a solution (has CurrentSolutionConfigurationContents set).
NuGet graph restore offers two ways to configure how the global properties set in the project that's being restored get passed to the helper application that does the graph operation, controlled by the property RestoreSerializeGlobalProperties. When true, the properties are serialized over stdin; when false they're passed on the command line.
@benwitmanmsft reported success setting <RestoreSerializeGlobalProperties>true</RestoreSerializeGlobalProperties> in his repro.
It looks like this problem arises when passing CurrentSolutionConfigurationContents on the command line--I'm guessing the command line parsing is eating the " characters.
@jeffkl I'm going to send this to y'all in NuGet.