diff --git a/dotnet/samples/04-hosting/DurableWorkflows/ConsoleApps/06_WorkflowSharedState/Executors.cs b/dotnet/samples/04-hosting/DurableWorkflows/ConsoleApps/06_WorkflowSharedState/Executors.cs index 57d2964c0c..5dd6d11526 100644 --- a/dotnet/samples/04-hosting/DurableWorkflows/ConsoleApps/06_WorkflowSharedState/Executors.cs +++ b/dotnet/samples/04-hosting/DurableWorkflows/ConsoleApps/06_WorkflowSharedState/Executors.cs @@ -38,6 +38,23 @@ internal sealed class ValidateOrder() : Executor("Validate string message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + try + { + return await HandleAsyncCore(message, context, cancellationToken); + } + catch (Exception ex) + { + Console.Error.WriteLine($"[DIAG] ValidateOrder.HandleAsync failed: {ex.GetType().FullName}: {ex.Message}"); + Console.Error.WriteLine($"[DIAG] StackTrace: {ex.StackTrace}"); + throw; + } + } + + private async ValueTask HandleAsyncCore( + string message, + IWorkflowContext context, + CancellationToken cancellationToken = default) { await Task.Delay(TimeSpan.FromMilliseconds(200), cancellationToken); diff --git a/dotnet/src/Microsoft.Agents.AI.DurableTask/Workflows/DurableActivityExecutor.cs b/dotnet/src/Microsoft.Agents.AI.DurableTask/Workflows/DurableActivityExecutor.cs index c9e9a1b125..d7497036cc 100644 --- a/dotnet/src/Microsoft.Agents.AI.DurableTask/Workflows/DurableActivityExecutor.cs +++ b/dotnet/src/Microsoft.Agents.AI.DurableTask/Workflows/DurableActivityExecutor.cs @@ -46,14 +46,46 @@ internal static class DurableActivityExecutor object typedInput = DeserializeInput(executorInput, inputType); DurableWorkflowContext workflowContext = new(sharedState, executor); - object? result = await executor.ExecuteCoreAsync( - typedInput, - new TypeId(inputType), - workflowContext, - WorkflowTelemetryContext.Disabled, - cancellationToken).ConfigureAwait(false); - return SerializeActivityOutput(result, workflowContext); + object? result; + try + { + result = await executor.ExecuteCoreAsync( + typedInput, + new TypeId(inputType), + workflowContext, + WorkflowTelemetryContext.Disabled, + cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + // Diagnostic logging to surface inner exception details in CI + Console.Error.WriteLine($"[DIAG] DurableActivityExecutor: ExecuteCoreAsync failed for '{binding.Id}' (inputType={inputType.FullName})"); + Console.Error.WriteLine($"[DIAG] Exception: {ex.GetType().FullName}: {ex.Message}"); + for (Exception? inner = ex.InnerException; inner is not null; inner = inner.InnerException) + { + Console.Error.WriteLine($"[DIAG] Inner: {inner.GetType().FullName}: {inner.Message}"); + Console.Error.WriteLine($"[DIAG] StackTrace: {inner.StackTrace}"); + } + + throw; + } + + string serialized; + try + { + serialized = SerializeActivityOutput(result, workflowContext); + } + catch (Exception ex) + { + Console.Error.WriteLine($"[DIAG] DurableActivityExecutor: SerializeActivityOutput failed for '{binding.Id}'"); + Console.Error.WriteLine($"[DIAG] Result type: {result?.GetType().FullName ?? "null"}"); + Console.Error.WriteLine($"[DIAG] Exception: {ex.GetType().FullName}: {ex.Message}"); + Console.Error.WriteLine($"[DIAG] StackTrace: {ex.StackTrace}"); + throw; + } + + return serialized; } private static string SerializeActivityOutput(object? result, DurableWorkflowContext context) diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/Executor.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/Executor.cs index d865b990c4..7f25e8021e 100644 --- a/dotnet/src/Microsoft.Agents.AI.Workflows/Executor.cs +++ b/dotnet/src/Microsoft.Agents.AI.Workflows/Executor.cs @@ -284,7 +284,11 @@ public abstract class Executor : IIdentified if (!result.IsSuccess) { - throw new TargetInvocationException($"Error invoking handler for {message.GetType()}", result.Exception); + // Include inner exception details for diagnostics (otherwise hidden by DTS FailureDetails) + string innerDetails = result.Exception is not null + ? $" --> {result.Exception.GetType().Name}: {result.Exception.Message}" + : string.Empty; + throw new TargetInvocationException($"Error invoking handler for {message.GetType()}{innerDetails}", result.Exception); } if (result.IsVoid)