Blazor WebAssemblyのErrorBoundaryでキャッチできない例外がある(ASP.NET CORE 6)

概要

この記事の内容は実際の挙動をもとにした推察になります。誤っている可能性があります。

Blazor WebAssemblyのページを<ErrorBoundary>のタグで括ると、ページ内で例外が発生した際にErrorBoundaryのOnErrorAsyncで例外をキャッチできるのですが、キャッチできないものがあります。

パターン1 非同期処理でのTaskCanceledException

ページ内のpublic async Taskの非同期メソッドの中でTaskCanceledExceptionが発生してもErrorBoundaryのOnErrorAsyncでキャッチされません。

たぶん、async Task自体のキャンセル扱いと取られてErrorBoundaryの処理対象外となっているのかもしれません。
実際に困るケースは、HttpClientの通信タイムアウトの時で、タイムアウトになるとTaskCanceledExceptionが発生します。

対策としては、HttpClientの処理をラップして、Try CatchでTaskCanceledExceptionをキャッチして、別の例外に置き換えてThrowします。

パターン2 別タスクで発生した例外

メソッドのなかで、Task.Runにより別タスクで処理を行い、その中で例外が発生した場合、ErrorBoundaryは例外をキャッチしません。

Task.Runの後にWait()を実行すれば、Wait実行時に例外が発生するので、この場合はErrorBoundaryで例外をキャッチします。
※別タスクで実行して投げっぱなしにするケースの場合に例外をキャッチしません。

パターン3 InputFileタグのOnChangeイベントから呼び出したメソッドで発生した例外

もうなぜだかさっぱりわかりません。
InputFileタグのOnChangeイベントから呼び出されたメソッドで発生した例外はことごとくErrorBoundaryでキャッチできません。

完全に推測ですが、InputFileタグのOnChangeから呼ばれたメソッドは完全に別タスク扱いになる(つまりパターン2と同じ状態になる)のではないかと思っています。

対策としては、メソッド内でTry Catchでエラーハンドリングして、メソッド内で適切に処理するしかなさそうです。

結論

そもそもErrorBoundaryで例外を一元処理する方針が間違っているのかもしれません。
例外は各メソッドでキャッチし、画面内の特定箇所やダイアログボックスでエラーがあった旨のメッセージを表示したほうがよいかもしれません。

なぜなら、Blazor WebAssemblyなどのいわゆるSPA系は昔のクライアントサーバシステムに似ているからです。
昔のクライアントサーバシステムは例外が発生すると、エラー画面に遷移させるのではなく、例外が発生した画面にエラーメッセージを表示するというスタイルで、SPAの場合もそのスタイルを踏襲したほうが自然なのかもしれません。