Skip to content

Commit 5e39089

Browse files
authored
Log unhandled exceptions thrown from command actions (#2114)
This PR adds explicit stderr logging for any exception thrown out of an ImageBuilder command's action handler. The root cause is that `System.CommandLine`'s default exception handler silently swallows `OperationCanceledException` (and `TaskCanceledException`, which derives from it), returning exit code 1 with zero diagnostic output. This makes any failure that surfaces as a cancellation invisible in pipeline logs (e.g. `HttpClient` timeout). The `check-base-image-updates` pipeline has been failing this way: after `READING MANIFEST`, the process exits 1 with no stack trace. This PR wraps the action body in `Command.TOptions.cs` with a try/catch that writes the full exception to `Console.Error`. Upstream issue: dotnet/command-line-api#2808
1 parent d8a3225 commit 5e39089

1 file changed

Lines changed: 20 additions & 8 deletions

File tree

src/ImageBuilder/Commands/Command.TOptions.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
using System;
66
using System.CommandLine;
7-
using System.CommandLine.Parsing;
8-
using System.Threading;
97
using System.Threading.Tasks;
108

119
namespace Microsoft.DotNet.ImageBuilder.Commands
@@ -33,15 +31,29 @@ public Command GetCliCommand()
3331

3432
cmd.SetAction(async (parseResult, cancellationToken) =>
3533
{
36-
options.Bind(parseResult);
34+
try
35+
{
36+
options.Bind(parseResult);
37+
38+
if (!options.NoVersionLogging)
39+
{
40+
LogDockerVersions();
41+
}
3742

38-
if (!options.NoVersionLogging)
43+
Initialize(options);
44+
await ExecuteAsync();
45+
}
46+
catch (Exception ex)
3947
{
40-
LogDockerVersions();
48+
// System.CommandLine silently swallows OperationCanceledException and TaskCanceledException, so
49+
// log all unhandled exceptions to stderr here and re-throw. This makes sure failures are always
50+
// observable in pipeline logs.
51+
// For more details, see https://github.com/dotnet/command-line-api/issues/2808.
52+
Console.Error.WriteLine($"Unhandled exception in command '{this.GetCommandName()}':");
53+
Console.Error.WriteLine(ex.ToString());
54+
Console.Error.Flush();
55+
throw;
4156
}
42-
43-
Initialize(options);
44-
await ExecuteAsync();
4557
});
4658

4759
return cmd;

0 commit comments

Comments
 (0)