From 426ce6b9336639db6d67f25538c111ea14ac90cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Prokop?= Date: Mon, 27 Apr 2026 09:03:48 +0200 Subject: [PATCH 1/5] added warning message for replaying, non fatal. --- .../BinaryLogger/BinaryLogReplayEventSource.cs | 9 ++++++++- src/Build/Resources/Strings.resx | 4 ++++ src/Build/Resources/xlf/Strings.cs.xlf | 5 +++++ src/Build/Resources/xlf/Strings.de.xlf | 5 +++++ src/Build/Resources/xlf/Strings.es.xlf | 5 +++++ src/Build/Resources/xlf/Strings.fr.xlf | 5 +++++ src/Build/Resources/xlf/Strings.it.xlf | 5 +++++ src/Build/Resources/xlf/Strings.ja.xlf | 5 +++++ src/Build/Resources/xlf/Strings.ko.xlf | 5 +++++ src/Build/Resources/xlf/Strings.pl.xlf | 5 +++++ src/Build/Resources/xlf/Strings.pt-BR.xlf | 5 +++++ src/Build/Resources/xlf/Strings.ru.xlf | 5 +++++ src/Build/Resources/xlf/Strings.tr.xlf | 5 +++++ src/Build/Resources/xlf/Strings.zh-Hans.xlf | 5 +++++ src/Build/Resources/xlf/Strings.zh-Hant.xlf | 5 +++++ src/MSBuild/XMake.cs | 14 +++++++++++++- 16 files changed, 90 insertions(+), 2 deletions(-) diff --git a/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs b/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs index 1e7ab846695..c9f307b2bf7 100644 --- a/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs +++ b/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs @@ -69,6 +69,13 @@ public sealed class BinaryLogReplayEventSource : public int FileFormatVersion => _fileFormatVersion ?? throw new InvalidOperationException(ResourceUtilities.GetResourceString("Binlog_Source_VersionUninitialized")); public int MinimumReaderVersion => _minimumReaderVersion ?? throw new InvalidOperationException(ResourceUtilities.GetResourceString("Binlog_Source_VersionUninitialized")); + /// + /// After replay, contains a warning message if the binlog was produced by a newer version of MSBuild; null otherwise. + /// + public string? FormatVersionMismatchWarning => _fileFormatVersion > BinaryLogger.FileFormatVersion + ? ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BinlogFormatVersionMismatch", _fileFormatVersion, BinaryLogger.FileFormatVersion) + : null; + /// Touches the static constructor /// to ensure it initializes /// and @@ -197,7 +204,7 @@ public static BuildEventArgsReader OpenBuildEventsReader(string sourceFilePath) /// A indicating the replay should stop as soon as possible. public void Replay(string sourceFilePath, CancellationToken cancellationToken) { - using var eventsReader = OpenBuildEventsReader(sourceFilePath); + using var eventsReader = OpenBuildEventsReader(OpenReader(sourceFilePath), true, AllowForwardCompatibility); Replay(eventsReader, cancellationToken); } diff --git a/src/Build/Resources/Strings.resx b/src/Build/Resources/Strings.resx index b4bed36c6bd..c79b070e4bb 100644 --- a/src/Build/Resources/Strings.resx +++ b/src/Build/Resources/Strings.resx @@ -2135,6 +2135,10 @@ Utilization: {0} Average Utilization: {1:###.0} LOCALIZATION: {0} is integer number denoting number of bytes. 'int.MaxValue' should not be translated. + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Custom check rule: '{0}' has been registered successfully. The message is emitted on successful loading of the custom check rule in process. diff --git a/src/Build/Resources/xlf/Strings.cs.xlf b/src/Build/Resources/xlf/Strings.cs.xlf index e25a9d8bbf5..99fabda1696 100644 --- a/src/Build/Resources/xlf/Strings.cs.xlf +++ b/src/Build/Resources/xlf/Strings.cs.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. Obsah se už získal jako StreamReader přes GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.de.xlf b/src/Build/Resources/xlf/Strings.de.xlf index 7ed77836b21..8d76b86c815 100644 --- a/src/Build/Resources/xlf/Strings.de.xlf +++ b/src/Build/Resources/xlf/Strings.de.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. Inhalt, der bereits als „StreamReader“ über „GetContentReader“ abgerufen wurde. diff --git a/src/Build/Resources/xlf/Strings.es.xlf b/src/Build/Resources/xlf/Strings.es.xlf index a6bf552039f..4c9f913ffec 100644 --- a/src/Build/Resources/xlf/Strings.es.xlf +++ b/src/Build/Resources/xlf/Strings.es.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. Contenido ya adquirido como StreamReader a través de GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.fr.xlf b/src/Build/Resources/xlf/Strings.fr.xlf index 74c62f3058f..9a370869cbc 100644 --- a/src/Build/Resources/xlf/Strings.fr.xlf +++ b/src/Build/Resources/xlf/Strings.fr.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. Contenu déjà acquis en tant que StreamReader par le biais de GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.it.xlf b/src/Build/Resources/xlf/Strings.it.xlf index a1bfcddfc5a..3b912454c98 100644 --- a/src/Build/Resources/xlf/Strings.it.xlf +++ b/src/Build/Resources/xlf/Strings.it.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. Contenuto già acquisito come StreamReader tramite GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.ja.xlf b/src/Build/Resources/xlf/Strings.ja.xlf index 5daeeb25828..3e7ed04a104 100644 --- a/src/Build/Resources/xlf/Strings.ja.xlf +++ b/src/Build/Resources/xlf/Strings.ja.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. GetContentReader を介して StreamReader として既に取得されたコンテンツ。 diff --git a/src/Build/Resources/xlf/Strings.ko.xlf b/src/Build/Resources/xlf/Strings.ko.xlf index ca31d528a30..b77674a4dfb 100644 --- a/src/Build/Resources/xlf/Strings.ko.xlf +++ b/src/Build/Resources/xlf/Strings.ko.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. GetContentReader를 통해 이미 StreamReader로 획득한 콘텐츠입니다. diff --git a/src/Build/Resources/xlf/Strings.pl.xlf b/src/Build/Resources/xlf/Strings.pl.xlf index 3ef14187401..47a0644a339 100644 --- a/src/Build/Resources/xlf/Strings.pl.xlf +++ b/src/Build/Resources/xlf/Strings.pl.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. Zawartość została już pobrana jako element StreamReader za pośrednictwem metody GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.pt-BR.xlf b/src/Build/Resources/xlf/Strings.pt-BR.xlf index 6334095e5b6..82c4f9b2b89 100644 --- a/src/Build/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Build/Resources/xlf/Strings.pt-BR.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. Conteúdo já adquirido como StreamReader por meio de GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.ru.xlf b/src/Build/Resources/xlf/Strings.ru.xlf index 0dbdc581f49..58d57e5703c 100644 --- a/src/Build/Resources/xlf/Strings.ru.xlf +++ b/src/Build/Resources/xlf/Strings.ru.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. Содержимое, уже получено как StreamReader через GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.tr.xlf b/src/Build/Resources/xlf/Strings.tr.xlf index 11758519b4c..af69dc391a5 100644 --- a/src/Build/Resources/xlf/Strings.tr.xlf +++ b/src/Build/Resources/xlf/Strings.tr.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. İçerik zaten GetContentReader ara StreamReader olarak alındı. diff --git a/src/Build/Resources/xlf/Strings.zh-Hans.xlf b/src/Build/Resources/xlf/Strings.zh-Hans.xlf index 6ca07df43f7..a5e732f9db4 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hans.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. 已通过 GetContentReader 以 StreamReader 形式获取的内容。 diff --git a/src/Build/Resources/xlf/Strings.zh-Hant.xlf b/src/Build/Resources/xlf/Strings.zh-Hant.xlf index 6f8a4402894..57d08aafc42 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hant.xlf @@ -36,6 +36,11 @@ {StrBegin="MSB4003: "}UE: Tasks are not allowed to use incorrect case for reserved attributes on the task nodes e.g. "continueonerror" instead of the "ContinueOnError". + + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + Content already acquired as StreamReader via GetContentReader. 內容已透過 GetContentReader 取得為 StreamReader。 diff --git a/src/MSBuild/XMake.cs b/src/MSBuild/XMake.cs index 60720e1d842..aeeea73c431 100644 --- a/src/MSBuild/XMake.cs +++ b/src/MSBuild/XMake.cs @@ -4046,7 +4046,8 @@ private static void ReplayBinaryLog( bool isBuildCheckEnabled) { - var replayEventSource = new BinaryLogReplayEventSource(); + var replayEventSource = new BinaryLogReplayEventSource() { AllowForwardCompatibility = true }; + replayEventSource.RecoverableReadError += _ => { }; var eventSource = isBuildCheckEnabled ? BuildCheckReplayModeConnector.GetMergedEventSource(BuildManager.DefaultBuildManager, replayEventSource) : @@ -4080,6 +4081,17 @@ private static void ReplayBinaryLog( try { replayEventSource.Replay(binaryLogFilePath, s_buildCancellationSource.Token); + + if (replayEventSource.FormatVersionMismatchWarning is string warning) + { + Console.WriteLine(warning); + } + } + catch (NotSupportedException ex) + { + // The log file format is not supported (e.g. minimum reader version too high). + var message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword("InvalidLogFileFormat", ex.Message); + Console.WriteLine(message); } catch (Exception ex) { From 9a87a075b328ba5c4af8bc3671a57b36342ff0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Prokop?= Date: Mon, 27 Apr 2026 09:21:01 +0200 Subject: [PATCH 2/5] generated unit tests --- src/Build.UnitTests/BinaryLogger_Tests.cs | 82 +++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/Build.UnitTests/BinaryLogger_Tests.cs b/src/Build.UnitTests/BinaryLogger_Tests.cs index 82d9c9194f4..fcdd3ebbad6 100644 --- a/src/Build.UnitTests/BinaryLogger_Tests.cs +++ b/src/Build.UnitTests/BinaryLogger_Tests.cs @@ -967,6 +967,88 @@ public void ProcessParameters_MixedConfigsWithDuplicates_HandledCorrectly() #endregion + #region Forward Compatibility Replay Tests + + [Fact] + public void OpenBuildEventsReader_ThrowsForIncompatibleVersion() + { + // fileFormatVersion > current AND minimumReaderVersion > current => fatal + var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream, Encoding.UTF8, leaveOpen: true); + writer.Write(BinaryLogger.FileFormatVersion + 10); // fileFormatVersion + writer.Write(BinaryLogger.FileFormatVersion + 5); // minimumReaderVersion (too high) + writer.Flush(); + stream.Position = 0; + + using var reader = new BinaryReader(stream); + Assert.Throws(() => + BinaryLogReplayEventSource.OpenBuildEventsReader(reader, closeInput: false, allowForwardCompatibility: true)); + + // Satisfy the ExpectFile constraint from the test fixture. + File.Create(_logFile).Dispose(); + } + + [Fact] + public void OpenBuildEventsReader_SucceedsForForwardCompatibleVersion() + { + // fileFormatVersion > current but minimumReaderVersion <= current => should succeed + var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream, Encoding.UTF8, leaveOpen: true); + writer.Write(BinaryLogger.FileFormatVersion + 5); // fileFormatVersion (newer) + writer.Write(BinaryLogger.ForwardCompatibilityMinimalVersion); // minimumReaderVersion (compatible) + writer.Flush(); + stream.Position = 0; + + using var reader = new BinaryReader(stream); + using var eventsReader = BinaryLogReplayEventSource.OpenBuildEventsReader(reader, closeInput: false, allowForwardCompatibility: true); + eventsReader.ShouldNotBeNull(); + eventsReader.FileFormatVersion.ShouldBe(BinaryLogger.FileFormatVersion + 5); + + File.Create(_logFile).Dispose(); + } + + [Fact] + public void OpenBuildEventsReader_ThrowsWithoutForwardCompatibility() + { + // fileFormatVersion > current, allowForwardCompatibility = false => fatal even if minimumReaderVersion is ok + var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream, Encoding.UTF8, leaveOpen: true); + writer.Write(BinaryLogger.FileFormatVersion + 5); // fileFormatVersion (newer) + writer.Write(BinaryLogger.ForwardCompatibilityMinimalVersion); // minimumReaderVersion (compatible) + writer.Flush(); + stream.Position = 0; + + using var reader = new BinaryReader(stream); + Assert.Throws(() => + BinaryLogReplayEventSource.OpenBuildEventsReader(reader, closeInput: false, allowForwardCompatibility: false)); + + File.Create(_logFile).Dispose(); + } + + [Fact] + public void FormatVersionMismatchWarning_NullForCurrentVersion() + { + using var env = TestEnvironment.Create(); + env.SetEnvironmentVariable("MSBUILDTARGETOUTPUTLOGGING", "1"); + + var binaryLogger = new BinaryLogger { Parameters = _logFile }; + + using (ProjectCollection collection = new()) + { + Project project = ObjectModelHelpers.CreateInMemoryProject(collection, s_testProject); + project.Build(new ILogger[] { binaryLogger }).ShouldBeTrue(); + } + + var replayEventSource = new BinaryLogReplayEventSource(); + replayEventSource.RecoverableReadError += _ => { }; + replayEventSource.BuildFinished += (_, _) => { }; + replayEventSource.Replay(_logFile); + + replayEventSource.FormatVersionMismatchWarning.ShouldBeNull(); + } + + #endregion + public void Dispose() { _env.Dispose(); From 06b6aed975e282e02567eca17deffdee30356567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Prokop?= Date: Mon, 27 Apr 2026 11:03:16 +0200 Subject: [PATCH 3/5] adressed copilot suggestions --- src/Build.UnitTests/BinaryLogger_Tests.cs | 7 +++---- .../Logging/BinaryLogger/BinaryLogReplayEventSource.cs | 4 ++-- src/Build/Resources/Strings.resx | 6 +++--- src/Build/Resources/xlf/Strings.cs.xlf | 6 +++--- src/Build/Resources/xlf/Strings.de.xlf | 6 +++--- src/Build/Resources/xlf/Strings.es.xlf | 6 +++--- src/Build/Resources/xlf/Strings.fr.xlf | 6 +++--- src/Build/Resources/xlf/Strings.it.xlf | 6 +++--- src/Build/Resources/xlf/Strings.ja.xlf | 6 +++--- src/Build/Resources/xlf/Strings.ko.xlf | 6 +++--- src/Build/Resources/xlf/Strings.pl.xlf | 6 +++--- src/Build/Resources/xlf/Strings.pt-BR.xlf | 6 +++--- src/Build/Resources/xlf/Strings.ru.xlf | 6 +++--- src/Build/Resources/xlf/Strings.tr.xlf | 6 +++--- src/Build/Resources/xlf/Strings.zh-Hans.xlf | 6 +++--- src/Build/Resources/xlf/Strings.zh-Hant.xlf | 6 +++--- 16 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/Build.UnitTests/BinaryLogger_Tests.cs b/src/Build.UnitTests/BinaryLogger_Tests.cs index fcdd3ebbad6..4efad4a5351 100644 --- a/src/Build.UnitTests/BinaryLogger_Tests.cs +++ b/src/Build.UnitTests/BinaryLogger_Tests.cs @@ -981,7 +981,7 @@ public void OpenBuildEventsReader_ThrowsForIncompatibleVersion() stream.Position = 0; using var reader = new BinaryReader(stream); - Assert.Throws(() => + Should.Throw(() => BinaryLogReplayEventSource.OpenBuildEventsReader(reader, closeInput: false, allowForwardCompatibility: true)); // Satisfy the ExpectFile constraint from the test fixture. @@ -1019,7 +1019,7 @@ public void OpenBuildEventsReader_ThrowsWithoutForwardCompatibility() stream.Position = 0; using var reader = new BinaryReader(stream); - Assert.Throws(() => + Should.Throw(() => BinaryLogReplayEventSource.OpenBuildEventsReader(reader, closeInput: false, allowForwardCompatibility: false)); File.Create(_logFile).Dispose(); @@ -1028,8 +1028,7 @@ public void OpenBuildEventsReader_ThrowsWithoutForwardCompatibility() [Fact] public void FormatVersionMismatchWarning_NullForCurrentVersion() { - using var env = TestEnvironment.Create(); - env.SetEnvironmentVariable("MSBUILDTARGETOUTPUTLOGGING", "1"); + _env.SetEnvironmentVariable("MSBUILDTARGETOUTPUTLOGGING", "1"); var binaryLogger = new BinaryLogger { Parameters = _logFile }; diff --git a/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs b/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs index c9f307b2bf7..2e1952c83a2 100644 --- a/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs +++ b/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs @@ -72,8 +72,8 @@ public sealed class BinaryLogReplayEventSource : /// /// After replay, contains a warning message if the binlog was produced by a newer version of MSBuild; null otherwise. /// - public string? FormatVersionMismatchWarning => _fileFormatVersion > BinaryLogger.FileFormatVersion - ? ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BinlogFormatVersionMismatch", _fileFormatVersion, BinaryLogger.FileFormatVersion) + public string? FormatVersionMismatchWarning => _fileFormatVersion is int version && version > BinaryLogger.FileFormatVersion + ? ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BinlogFormatVersionMismatch", version, BinaryLogger.FileFormatVersion) : null; /// Touches the static constructor diff --git a/src/Build/Resources/Strings.resx b/src/Build/Resources/Strings.resx index c79b070e4bb..b63e28e1a7f 100644 --- a/src/Build/Resources/Strings.resx +++ b/src/Build/Resources/Strings.resx @@ -2136,8 +2136,8 @@ Utilization: {0} Average Utilization: {1:###.0} - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Custom check rule: '{0}' has been registered successfully. @@ -2481,7 +2481,7 @@ Utilization: {0} Average Utilization: {1:###.0} diff --git a/src/Build/Resources/xlf/Strings.cs.xlf b/src/Build/Resources/xlf/Strings.cs.xlf index 99fabda1696..d477592535b 100644 --- a/src/Build/Resources/xlf/Strings.cs.xlf +++ b/src/Build/Resources/xlf/Strings.cs.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.de.xlf b/src/Build/Resources/xlf/Strings.de.xlf index 8d76b86c815..b077163c95f 100644 --- a/src/Build/Resources/xlf/Strings.de.xlf +++ b/src/Build/Resources/xlf/Strings.de.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.es.xlf b/src/Build/Resources/xlf/Strings.es.xlf index 4c9f913ffec..55684896818 100644 --- a/src/Build/Resources/xlf/Strings.es.xlf +++ b/src/Build/Resources/xlf/Strings.es.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.fr.xlf b/src/Build/Resources/xlf/Strings.fr.xlf index 9a370869cbc..5a75745c25b 100644 --- a/src/Build/Resources/xlf/Strings.fr.xlf +++ b/src/Build/Resources/xlf/Strings.fr.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.it.xlf b/src/Build/Resources/xlf/Strings.it.xlf index 3b912454c98..2b5d85c0ef0 100644 --- a/src/Build/Resources/xlf/Strings.it.xlf +++ b/src/Build/Resources/xlf/Strings.it.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.ja.xlf b/src/Build/Resources/xlf/Strings.ja.xlf index 3e7ed04a104..f493adcfa47 100644 --- a/src/Build/Resources/xlf/Strings.ja.xlf +++ b/src/Build/Resources/xlf/Strings.ja.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.ko.xlf b/src/Build/Resources/xlf/Strings.ko.xlf index b77674a4dfb..0196db61439 100644 --- a/src/Build/Resources/xlf/Strings.ko.xlf +++ b/src/Build/Resources/xlf/Strings.ko.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.pl.xlf b/src/Build/Resources/xlf/Strings.pl.xlf index 47a0644a339..62a054e5ee6 100644 --- a/src/Build/Resources/xlf/Strings.pl.xlf +++ b/src/Build/Resources/xlf/Strings.pl.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.pt-BR.xlf b/src/Build/Resources/xlf/Strings.pt-BR.xlf index 82c4f9b2b89..e5cc39449cf 100644 --- a/src/Build/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Build/Resources/xlf/Strings.pt-BR.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.ru.xlf b/src/Build/Resources/xlf/Strings.ru.xlf index 58d57e5703c..656a412dfee 100644 --- a/src/Build/Resources/xlf/Strings.ru.xlf +++ b/src/Build/Resources/xlf/Strings.ru.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.tr.xlf b/src/Build/Resources/xlf/Strings.tr.xlf index af69dc391a5..b7a6b30f8ec 100644 --- a/src/Build/Resources/xlf/Strings.tr.xlf +++ b/src/Build/Resources/xlf/Strings.tr.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.zh-Hans.xlf b/src/Build/Resources/xlf/Strings.zh-Hans.xlf index a5e732f9db4..58c01e2ed66 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hans.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. diff --git a/src/Build/Resources/xlf/Strings.zh-Hant.xlf b/src/Build/Resources/xlf/Strings.zh-Hant.xlf index 57d08aafc42..519dfb332d7 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hant.xlf @@ -37,9 +37,9 @@ instead of the "ContinueOnError". - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - MSB4268: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. - {StrBegin="MSB4268: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + MSB4281: The binary log file was created with a newer version of MSBuild (format version {0}) than the current version (format version {1}). Some data may be missing from the replay. + {StrBegin="MSB4281: "}{0} is the binlog file format version. {1} is the current MSBuild file format version. Content already acquired as StreamReader via GetContentReader. From 00719f9d96e08f4e2c0a77c68d2278d3c8a5fc4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Prokop?= Date: Wed, 29 Apr 2026 17:08:48 +0200 Subject: [PATCH 4/5] adressed comments --- src/Build.UnitTests/BinaryLogger_Tests.cs | 44 +++++++++++++++++-- .../BinaryLogReplayEventSource.cs | 20 ++++++--- src/MSBuild/XMake.cs | 4 ++ 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/Build.UnitTests/BinaryLogger_Tests.cs b/src/Build.UnitTests/BinaryLogger_Tests.cs index 4efad4a5351..e47fb19b1e2 100644 --- a/src/Build.UnitTests/BinaryLogger_Tests.cs +++ b/src/Build.UnitTests/BinaryLogger_Tests.cs @@ -7,6 +7,7 @@ using System.IO.Compression; using System.Linq; using System.Text; +using System.Threading; using FakeItEasy; using FluentAssertions; using Microsoft.Build.BackEnd.Logging; @@ -968,6 +969,8 @@ public void ProcessParameters_MixedConfigsWithDuplicates_HandledCorrectly() #endregion #region Forward Compatibility Replay Tests + // These tests exercise in-memory streams rather than .binlog files, + // but the fixture's _logFile must exist at Dispose time. [Fact] public void OpenBuildEventsReader_ThrowsForIncompatibleVersion() @@ -984,8 +987,7 @@ public void OpenBuildEventsReader_ThrowsForIncompatibleVersion() Should.Throw(() => BinaryLogReplayEventSource.OpenBuildEventsReader(reader, closeInput: false, allowForwardCompatibility: true)); - // Satisfy the ExpectFile constraint from the test fixture. - File.Create(_logFile).Dispose(); + CreateExpectedLogFile(); } [Fact] @@ -1004,7 +1006,7 @@ public void OpenBuildEventsReader_SucceedsForForwardCompatibleVersion() eventsReader.ShouldNotBeNull(); eventsReader.FileFormatVersion.ShouldBe(BinaryLogger.FileFormatVersion + 5); - File.Create(_logFile).Dispose(); + CreateExpectedLogFile(); } [Fact] @@ -1022,9 +1024,15 @@ public void OpenBuildEventsReader_ThrowsWithoutForwardCompatibility() Should.Throw(() => BinaryLogReplayEventSource.OpenBuildEventsReader(reader, closeInput: false, allowForwardCompatibility: false)); - File.Create(_logFile).Dispose(); + CreateExpectedLogFile(); } + /// + /// Creates an empty placeholder so the fixture's Dispose doesn't fail + /// when the test didn't produce a real .binlog file. + /// + private void CreateExpectedLogFile() => File.Create(_logFile).Dispose(); + [Fact] public void FormatVersionMismatchWarning_NullForCurrentVersion() { @@ -1046,6 +1054,34 @@ public void FormatVersionMismatchWarning_NullForCurrentVersion() replayEventSource.FormatVersionMismatchWarning.ShouldBeNull(); } + [Fact] + public void FormatVersionMismatchWarning_NonNullForNewerVersion() + { + int newerVersion = BinaryLogger.FileFormatVersion + 5; + + var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream, Encoding.UTF8, leaveOpen: true); + writer.Write(newerVersion); // fileFormatVersion + writer.Write(BinaryLogger.ForwardCompatibilityMinimalVersion); // minimumReaderVersion + stream.WriteByte(0); // EndOfFile record + writer.Flush(); + stream.Position = 0; + + using var binaryReader = new BinaryReader(stream); + using var eventsReader = BinaryLogReplayEventSource.OpenBuildEventsReader(binaryReader, closeInput: false, allowForwardCompatibility: true); + + var replayEventSource = new BinaryLogReplayEventSource(); + replayEventSource.RecoverableReadError += _ => { }; + replayEventSource.BuildFinished += (_, _) => { }; + replayEventSource.Replay(eventsReader, CancellationToken.None); + + replayEventSource.FormatVersionMismatchWarning.ShouldNotBeNull(); + replayEventSource.FormatVersionMismatchWarning.ShouldContain(newerVersion.ToString()); + replayEventSource.FormatVersionMismatchWarning.ShouldContain(BinaryLogger.FileFormatVersion.ToString()); + + CreateExpectedLogFile(); + } + #endregion public void Dispose() diff --git a/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs b/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs index 2e1952c83a2..a5f000fddd9 100644 --- a/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs +++ b/src/Build/Logging/BinaryLogger/BinaryLogReplayEventSource.cs @@ -65,16 +65,16 @@ public sealed class BinaryLogReplayEventSource : { private int? _fileFormatVersion; private int? _minimumReaderVersion; + private string? _formatVersionMismatchWarning; public int FileFormatVersion => _fileFormatVersion ?? throw new InvalidOperationException(ResourceUtilities.GetResourceString("Binlog_Source_VersionUninitialized")); public int MinimumReaderVersion => _minimumReaderVersion ?? throw new InvalidOperationException(ResourceUtilities.GetResourceString("Binlog_Source_VersionUninitialized")); /// - /// After replay, contains a warning message if the binlog was produced by a newer version of MSBuild; null otherwise. + /// After replay, contains a warning message if the binlog was produced by a newer version of MSBuild. + /// Returns if has not been called yet or if the versions match. /// - public string? FormatVersionMismatchWarning => _fileFormatVersion is int version && version > BinaryLogger.FileFormatVersion - ? ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BinlogFormatVersionMismatch", version, BinaryLogger.FileFormatVersion) - : null; + public string? FormatVersionMismatchWarning => _formatVersionMismatchWarning; /// Touches the static constructor /// to ensure it initializes @@ -237,6 +237,9 @@ public void Replay(BuildEventArgsReader reader, CancellationToken cancellationTo { _fileFormatVersion = reader.FileFormatVersion; _minimumReaderVersion = reader.MinimumReaderVersion; + _formatVersionMismatchWarning = reader.FileFormatVersion > BinaryLogger.FileFormatVersion + ? ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BinlogFormatVersionMismatch", reader.FileFormatVersion, BinaryLogger.FileFormatVersion) + : null; bool supportsForwardCompatibility = reader.FileFormatVersion >= BinaryLogger.ForwardCompatibilityMinimalVersion; // Allow any possible deferred subscriptions to be registered @@ -261,9 +264,12 @@ public void Replay(BuildEventArgsReader reader, CancellationToken cancellationTo ResourceUtilities.GetResourceString("Binlog_Source_MultiSubscribeError")); } - // Forward compatible reading makes sense only for structured events reading. - reader.SkipUnknownEvents = supportsForwardCompatibility && AllowForwardCompatibility; - reader.SkipUnknownEventParts = supportsForwardCompatibility && AllowForwardCompatibility; + // Forward compatible reading makes sense only for structured events reading + // and only when the binlog is actually from a newer version. + bool skipUnknown = supportsForwardCompatibility && AllowForwardCompatibility + && reader.FileFormatVersion > BinaryLogger.FileFormatVersion; + reader.SkipUnknownEvents = skipUnknown; + reader.SkipUnknownEventParts = skipUnknown; reader.RecoverableReadError += RecoverableReadError; while (!cancellationToken.IsCancellationRequested && reader.Read() is { } instance) diff --git a/src/MSBuild/XMake.cs b/src/MSBuild/XMake.cs index aeeea73c431..a7bcb751982 100644 --- a/src/MSBuild/XMake.cs +++ b/src/MSBuild/XMake.cs @@ -4047,6 +4047,10 @@ private static void ReplayBinaryLog( { var replayEventSource = new BinaryLogReplayEventSource() { AllowForwardCompatibility = true }; + + // Required when AllowForwardCompatibility is true — the reader requires a subscriber + // for recoverable errors when skipping unknown events from newer-version binlogs. + // For same-version binlogs the skip flags are not set, so this handler never fires. replayEventSource.RecoverableReadError += _ => { }; var eventSource = isBuildCheckEnabled ? From db82f812b756332815eab68f4ccc5579818a6ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Prokop?= Date: Thu, 30 Apr 2026 16:52:32 +0200 Subject: [PATCH 5/5] deleted unnecessary catch block. --- src/MSBuild/XMake.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/MSBuild/XMake.cs b/src/MSBuild/XMake.cs index a7bcb751982..b14b0d45b29 100644 --- a/src/MSBuild/XMake.cs +++ b/src/MSBuild/XMake.cs @@ -4091,12 +4091,6 @@ private static void ReplayBinaryLog( Console.WriteLine(warning); } } - catch (NotSupportedException ex) - { - // The log file format is not supported (e.g. minimum reader version too high). - var message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword("InvalidLogFileFormat", ex.Message); - Console.WriteLine(message); - } catch (Exception ex) { var message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword("InvalidLogFileFormat", ex.Message);