From ba2963d892b3713ab315b5de68cce45ee8e7c050 Mon Sep 17 00:00:00 2001 From: Gagik Kyurkchyan Date: Fri, 1 May 2026 13:41:13 +0400 Subject: [PATCH] Surface unhandled exceptions in CLI and TestHarness The outer catch in CommandExecutionService silently swallowed any exception not handled by BaseCommandHandler's specific catches (auth, ServiceBus, cancellation), so failures like missing queues or unexpected errors exited with code 1 and no output. Print the exception to stderr in the safety net, and add a generic catch in BaseCommandHandler so handler errors get formatted via IConsoleOutput with stack traces under --verbose. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/ServiceBusToolset.CLI/CommandExecutionService.cs | 8 +++++++- .../Commands/BaseCommandHandler{TCommand,TResult}.cs | 6 ++++++ .../CommandExecutionService.cs | 8 +++++++- .../Common/Commands/BaseCommandHandler.cs | 6 ++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/ServiceBusToolset.CLI/CommandExecutionService.cs b/src/ServiceBusToolset.CLI/CommandExecutionService.cs index 1f3a4bc..131bcfe 100644 --- a/src/ServiceBusToolset.CLI/CommandExecutionService.cs +++ b/src/ServiceBusToolset.CLI/CommandExecutionService.cs @@ -36,8 +36,14 @@ await result .WithCommandAsync(cmd => HandleCommandAsync(cmd, stoppingToken)) .WithNotParsedAsync(HandleParseErrors); } - catch (Exception) + catch (Exception ex) { + Console.ResetColor(); + Console.ForegroundColor = ConsoleColor.Red; + Console.Error.WriteLine(); + Console.Error.WriteLine($"Unhandled error: {ex.GetType().Name}: {ex.Message}"); + Console.Error.WriteLine(ex.ToString()); + Console.ResetColor(); Environment.ExitCode = 1; } finally diff --git a/src/ServiceBusToolset.CLI/Common/Commands/BaseCommandHandler{TCommand,TResult}.cs b/src/ServiceBusToolset.CLI/Common/Commands/BaseCommandHandler{TCommand,TResult}.cs index 4be0d85..ba42e54 100644 --- a/src/ServiceBusToolset.CLI/Common/Commands/BaseCommandHandler{TCommand,TResult}.cs +++ b/src/ServiceBusToolset.CLI/Common/Commands/BaseCommandHandler{TCommand,TResult}.cs @@ -43,6 +43,12 @@ public async Task ExecuteAsync(TCommand command, Output.Warning("\nOperation cancelled."); return 1; } + catch (Exception ex) + { + Output.Error($"Unexpected error: {ex.GetType().Name}: {ex.Message}"); + Output.Verbose(ex.ToString(), verbose); + return 1; + } } protected abstract Task> ExecuteCoreAsync(TCommand command, bool verbose, CancellationToken cancellationToken = default); diff --git a/src/ServiceBusToolset.TestHarness/CommandExecutionService.cs b/src/ServiceBusToolset.TestHarness/CommandExecutionService.cs index 472ba75..abcea44 100644 --- a/src/ServiceBusToolset.TestHarness/CommandExecutionService.cs +++ b/src/ServiceBusToolset.TestHarness/CommandExecutionService.cs @@ -21,8 +21,14 @@ await result .WithCommandAsync(cmd => HandleCommandAsync(cmd, stoppingToken)) .WithNotParsedAsync(HandleParseErrors); } - catch (Exception) + catch (Exception ex) { + Console.ResetColor(); + Console.ForegroundColor = ConsoleColor.Red; + Console.Error.WriteLine(); + Console.Error.WriteLine($"Unhandled error: {ex.GetType().Name}: {ex.Message}"); + Console.Error.WriteLine(ex.ToString()); + Console.ResetColor(); Environment.ExitCode = 1; } finally diff --git a/src/ServiceBusToolset.TestHarness/Common/Commands/BaseCommandHandler.cs b/src/ServiceBusToolset.TestHarness/Common/Commands/BaseCommandHandler.cs index 2ccd244..1179970 100644 --- a/src/ServiceBusToolset.TestHarness/Common/Commands/BaseCommandHandler.cs +++ b/src/ServiceBusToolset.TestHarness/Common/Commands/BaseCommandHandler.cs @@ -41,6 +41,12 @@ public async Task ExecuteAsync(TCommand command, Output.Warning("\nOperation cancelled."); return 1; } + catch (Exception ex) + { + Output.Error($"Unexpected error: {ex.GetType().Name}: {ex.Message}"); + Output.Verbose(ex.ToString(), verbose); + return 1; + } } protected abstract Task ExecuteCoreAsync(TCommand command, bool verbose, CancellationToken cancellationToken = default);