Skip to content

VBCSCompilerLogger: MissingMethodException on CommandLineArguments.Errors - not wrapped in tryAccessCommandLineArgument #1354

@HelcioMEng

Description

@HelcioMEng

I had help of AI generated information regarding this issue and I hope information below is useful.

Summary
VBCSCompilerLogger crashes with MissingMethodException when used with MSBuild installations that ship a different version of Microsoft.CodeAnalysis than what the logger was compiled against. The CommandLineArguments.Errors property access is not wrapped in the tryAccessCommandLineArgument helper, unlike other version-sensitive property accesses in the same file.

Environment
BuildXL: 0.1.0-devBuild (built from source, C:\tools\BuildXL-src\Out\Bin\Debug\win-x64\bxl.exe)
MSBuild: 17.x (Visual Studio 2022 BuildTools / Professional)
MsBuild resolver with msBuildRuntime: "FullFramework", useManagedSharedCompilation: true
Windows build nodes
Error (Option A — standard VBCSCompilerLogger.dll from Out\Bin\Debug\win-x64\tools\vbcslogger\net472)

MSBUILD : error MSB4017: The build stopped unexpectedly because of an unexpected logger failure.
Microsoft.Build.Exceptions.InternalLoggerException: The build stopped unexpectedly because of an unexpected logger failure.
---> System.MissingMethodException: Method not found:
'System.Collections.Immutable.ImmutableArray`1<Microsoft.CodeAnalysis.Diagnostic>
Microsoft.CodeAnalysis.CommandLineArguments.get_Errors()'.
at VBCSCompilerLogger.VBCSCompilerLogger.EventSourceOnMessageRaised(Object sender, BuildMessageEventArgs e)

Error (Option B — VBCSCompilerLoggerOldCodeAnalysis.dll from Out\Objects...\testRun\Logger, renamed to VBCSCompilerLogger.dll)

MSBUILD : error MSB1028: The logger failed unexpectedly.
System.IO.FileNotFoundException: Could not load file or assembly
'Microsoft.CodeAnalysis, Version=2.10.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
or one of its dependencies. The system cannot find the file specified.
at VBCSCompilerLogger.VBCSCompilerLogger..ctor()

Root Cause
In VBCSCompilerLogger.cs, the EventSourceOnMessageRaised method accesses parsedCommandLine.Errors directly:
IEnumerable badSwitchErrors = parsedCommandLine.Errors
.Where(diagnostic => diagnostic.Id.Contains("2007")).ToList();

This property was added in a newer version of Microsoft.CodeAnalysis. Unlike other version-sensitive accesses in the same method (e.g., AnalyzerReferences, EmbeddedFiles, AdditionalFiles, AnalyzerConfigPaths, ErrorLogOptions, etc.), the .Errors property is not wrapped in the tryAccessCommandLineArgument helper that gracefully handles MissingMethodException:

static T? tryAccessCommandLineArgument(Func accessCommandLineArgument)
{
try { return accessCommandLineArgument(); }
catch (MissingMethodException) { return default; }
}

Proposed Fix
Wrap the parsedCommandLine.Errors access in tryAccessCommandLineArgument:

ImmutableArray errors = tryAccessCommandLineArgument(() => parsedCommandLine.Errors);
IEnumerable badSwitchErrors = errors != default
? errors.Where(diagnostic => diagnostic.Id.Contains("2007")).ToList()
: Enumerable.Empty();

his is consistent with how all other version-sensitive CommandLineArguments properties are accessed in the same method.

Workaround
Set useManagedSharedCompilation: false in the resolver configuration. This disables the VBCSCompilerLogger entirely but results in slightly slower C# builds (no shared Roslyn compiler service).

Thanks a lot

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions