When an activity function or a sub-orchestration throws an exception, it propogates up to the parent orchestrator function as a FunctionFailedException. It contains an InnerException value which has the same message as the original exception, but the type information is not preserved. Rather, it is always a System.Exception.
Ideally, the original exception is preserved.
The problem is with the serialization settings between when the exception is observed by the activity function executor (type information is written) and the parent orchestrator (type information is ignored). The fix may require changes to the Durable Task Framework.
Any update on this issue?
In my opinion this is vital for proper error handling for activity functions, especially when using CallActivityWithRetryAsync
@armadak Still trying to figure out the right way to fix this. It turns out the serialization of exceptions in .NET is quite tricky for a variety of different reasons.
"{\"ExceptionType\":\"Microsoft.Azure.WebJobs.FunctionFailedException\",\"InnerExceptionType\":\"DurableTask.Core.Exceptions.TaskFailedExceptionDeserializationException\"}"
TaskFailedExceptionDeserializationException
Instead of trying to serialize/deserialize the whole exception object,
Can you not just throw the exception where it contains
public class ActivityException : Exception{
public string ActivityName{get;private set;}
public string ExceptionTypeName{get;private set;}
public string ExceptionTypeMessage{get;private set;}
public string InnerExceptionTypeName{get;private set;}
public string InnerExceptionTypeMessage{get;private set;}
}
I need to have at least ActivityName or FunctionName where the exception being thrown
@andrew-vandenbrink Thanks for the suggestion - Yes, that's one option I'm considering. It would likely look a little different though since we also want to make it usable in other languages supported by the Azure Functions runtime.
@cgillum I tried simple solution. Adding TypeNameHandling to exception serializer settings.
Exception objects always inherit Exception class, they are serialized to base class even if they do not exist.
https://github.com/Azure/azure-functions-durable-extension/compare/dev...shibayan:exception-serializer-setting
try
{
await context.CallActivityWithRetryAsync<string>("Function1_Hello", new RetryOptions(TimeSpan.FromSeconds(5), 1)
{
Handle = ex =>
{
// It's work
return ex.InnerException is InvalidOperationException;
}
}, null);
}
catch (FunctionFailedException ex) when (ex.InnerException is InvalidOperationException)
{
// It's Work
}

Thanks
@shibayan Interesting - I'm wondering how I could I could have overlooked this 馃槄. Thank you for sharing the example. We'll take a look and see if we can use this approach to help resolve this item.
Resolved with v1.8.0 release.