From 2b0717464b2387158c4f3a1f14c23f48f9241178 Mon Sep 17 00:00:00 2001 From: w3lld1 <42353747+w3lld1@users.noreply.github.com> Date: Thu, 16 Jul 2026 01:57:10 +0200 Subject: [PATCH] Log cancellation exceptions I report cancellation exceptions through the default error handler instead of silently swallowing their diagnostics. --- .../UseExceptionHandlerTests.cs | 18 +++++++++++------- .../Invocation/InvocationPipeline.cs | 15 ++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/System.CommandLine.Tests/UseExceptionHandlerTests.cs b/src/System.CommandLine.Tests/UseExceptionHandlerTests.cs index 201f0ee869..d057acb3aa 100644 --- a/src/System.CommandLine.Tests/UseExceptionHandlerTests.cs +++ b/src/System.CommandLine.Tests/UseExceptionHandlerTests.cs @@ -35,19 +35,23 @@ public async Task UseExceptionHandler_catches_command_handler_exceptions_and_wri error.ToString().Should().Contain("System.Exception: oops!"); } - [Fact] - public async Task When_thrown_exception_is_from_cancelation_no_output_is_generated() + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task UseExceptionHandler_writes_cancellation_exception_details_to_standard_error(bool taskCanceled) { Command command = new("the-command"); - command.SetAction((_, __) => throw new OperationCanceledException()); + Exception exception = taskCanceled + ? new TaskCanceledException("task canceled") + : new OperationCanceledException("operation canceled"); + command.SetAction((_, __) => throw exception); - var output = new StringWriter(); var error = new StringWriter(); - int resultCode = await command.Parse("the-command").InvokeAsync(new() { Output = output, Error = error }, CancellationToken.None); + int resultCode = await command.Parse("the-command").InvokeAsync(new() { Error = error }, CancellationToken.None); - output.ToString().Should().BeEmpty(); - resultCode.Should().NotBe(0); + error.ToString().Should().Contain(exception.ToString()); + resultCode.Should().Be(1); } [Theory] diff --git a/src/System.CommandLine/Invocation/InvocationPipeline.cs b/src/System.CommandLine/Invocation/InvocationPipeline.cs index e8fe7c435f..26e21a98f4 100644 --- a/src/System.CommandLine/Invocation/InvocationPipeline.cs +++ b/src/System.CommandLine/Invocation/InvocationPipeline.cs @@ -138,18 +138,15 @@ internal static int Invoke(ParseResult parseResult) private static int DefaultExceptionHandler(Exception exception, ParseResult parseResult) { - if (exception is not OperationCanceledException) - { - ConsoleHelpers.ResetTerminalForegroundColor(); - ConsoleHelpers.SetTerminalForegroundRed(); + ConsoleHelpers.ResetTerminalForegroundColor(); + ConsoleHelpers.SetTerminalForegroundRed(); - var error = parseResult.InvocationConfiguration.Error; + var error = parseResult.InvocationConfiguration.Error; - error.Write(LocalizationResources.ExceptionHandlerHeader()); - error.WriteLine(exception.ToString()); + error.Write(LocalizationResources.ExceptionHandlerHeader()); + error.WriteLine(exception.ToString()); - ConsoleHelpers.ResetTerminalForegroundColor(); - } + ConsoleHelpers.ResetTerminalForegroundColor(); return 1; }