aspnetcore: Break on first-chance exception in Web Assembly debugger

Update: The actual request here is being able to have the debugger break if there’s an unhandled exception. Please disregard the stuff about AppDomain.CurrentDomain.UnhandledException.


Original report

Looks like this is an issue impacting the community: https://www.reddit.com/r/Blazor/comments/vhrrl1/blazor_wasm_how_to_break_on_unhandled_exception/

Ideally we can hook into the System.AppDomain.CurrentDomain.UnhandledException as we do with WebView for WinForms / WPF.

Repro:

Index.razor:

<button @onclick="ThrowException">Throw Exception</button>

@code {
    public void ThrowException()
    {
        throw new Exception("throwing new ex");
    }
}

Program.cs:

System.AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
{
    System.Console.WriteLine("!!! Encountered exception !!!");
};

Expected: !!! Encountered exception !!! console output Actual: The exception breaks the world // stack trace dumps to console

Kind of related: https://github.com/dotnet/maui/issues/5535

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 25 (21 by maintainers)

Most upvoted comments

@jasonswearingen I would not say @thaystg is a mitigation, it is working as expected.

It is unfortunate that the runtime throws many exceptions during boot, however that is a separate problem.

For completeness, does it not work for you if you turn on the JavaScript Exceptions -> All Exceptions after the app has started?

@SteveSandersonMS I think we might just want to rethrow after we log the exception. That said, we would need to check if that changes the behavior, as I would expect that to crash the app, which if it currently does not, is a big breaking change. I vaguely recall this behavior being “by design”, as we didn’t care for the exceptions happening on the client (compared to server or now desktop). The reasoning I think it was something like, “an exception happened” but the app is likely to continue working afterwards, so we shouldn’t actively prevent it and force a “refresh”.

@TanayParikh if its about breaking when an exception happens, we shouldn’t do anything in the framework for it, “Break for first chance exceptions” is a debugger feature. We should make sure that it works in all platforms.

should we perhaps be doing something different so that Blazor doesn’t catch (or intentionally re-throw) the unhandled exception

Maybe. In WebAssemblyRenderer, we override HandleException and call Log.UnhandledExceptionRenderingComponent(..., exception, ...). Maybe we need to be rethrowing it instead.

The way the logging there works is a bit magical - the implementation comes from some kind of codegen based on a [LoggerMessage] attribute, so it’s tough to see what it actually does internally. Maybe we should not be using that logic and should just rethrow instead.

To be clear, it will not pause in unhandled exception because the exception is caught by blazor code. So the user should check the “pause on all exceptions”, then it will pause in the “unhandled” one.

image

@javiercn Will this case get added to the manual tests?

I’ll take care of it 😄

@javiercn Will this case get added to the manual tests?

This is not working because of two reasons: First of them is this issue that I have just opened that is completely unrelated to exceptions: https://github.com/dotnet/runtime/issues/71456

The second reason is that on Blazor code this exception is been caught. So we need to enable “all exceptions” in exception settings. image

Then it will pause correctly in the exception: image

This is a functionality of the debugger, if it doesn’t work, we shouldn’t workaround anything in the framework. We should report it to the right folks to make sure that the experience is fixed. The instructions below are for VS, but applies to VS Code and VS 4 Mac in the same way.

https://docs.microsoft.com/en-us/visualstudio/debugger/managing-exceptions-with-the-debugger?view=vs-2022#tell-the-debugger-to-break-when-an-exception-is-thrown