Skip to content

MSBuild 18 breaks custom loggers that inherit from ConsoleLogger #12747

@rainersigwald

Description

@rainersigwald

A Microsoft-internal team adopting MSBuild 18/Visual Studio 2026 reported that their custom logger was crashing with the callstack

1>Microsoft.Build.Exceptions.InternalLoggerException: The build stopped unexpectedly because of an unexpected logger failure. ---> System.NullReferenceException: Object reference not set to an instance of an object.
1>   at Microsoft.Build.BackEnd.Logging.ParallelConsoleLogger.WriteMessageAligned(String message, Boolean prefixAlreadyWritten, Int32 prefixAdjustment)
1>   at Microsoft.Build.BackEnd.Logging.ParallelConsoleLogger.DisplayDeferredProjectStartedEvent(BuildEventContext e)
1>   at Microsoft.Build.BackEnd.Logging.ParallelConsoleLogger.DisplayDeferredStartedEvents(BuildEventContext e)
1>   at Microsoft.Build.BackEnd.Logging.ParallelConsoleLogger.MessageHandler(Object sender, BuildMessageEventArgs e)
1>   at Microsoft.Build.Framework.BuildMessageEventHandler.Invoke(Object sender, BuildMessageEventArgs e)
1>   at Microsoft.Build.BackEnd.Logging.EventSourceSink.Consume(BuildEventArgs buildEvent)
1>   --- End of inner exception stack trace ---
1>   at Microsoft.Build.Exceptions.InternalLoggerException.Throw(Exception innerException, BuildEventArgs e, String messageResourceName, Boolean initializationException, String[] messageArgs)
1>   at Microsoft.Build.BackEnd.Logging.EventSourceSink.Consume(BuildEventArgs buildEvent)
1>   at Microsoft.Build.BackEnd.Logging.EventSourceSink.RaiseAnyEvent(BuildEventArgs buildEvent)

I helped debug and the problem arose when #12336 changed the no-configuration default backing logger for ConsoleLogger._consoleLogger from SerialConsoleLogger to ParallelConsoleLogger.

The custom logger in question overrides ConsoleLogger.Initialize and does not call base.Initialize. That and BuildFinishedHandler are the only entrypoints to CheckIfOutputSupportsAlignment() so it didn't get called, meaning it didn't get to run

_consoleOutputAligner = new ConsoleOutputAligner(_bufferWidth, _alignMessages, (IStringBuilderProvider)this);

so _consoleOutputAligner is null in

WriteHandler(_consoleOutputAligner.AlignConsoleOutput(message, prefixAlreadyWritten, adjustedPrefixWidth));

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions