⚠️

Next15のエラーハンドリング変更点

に公開

はじめに

Next15が昨年10月下旬にリリースされました。そこで半年遅れではありますが手元のプロジェクトをNext14から15に上げるかと思い腰を上げました。
破壊的な変更は公式に記載の2点(Async Request APIsとCaching Semantics)で、どちらも影響ないだろうと思いしれっとバージョンを上げたら、あらびっくり、Nextのエラー(左下にトーストで出るやつ。以下エラーオーバーレイと書く)が発生しあわあわしました。
結論development modeに限った話、かつアプリケーションの機能的な問題には影響がなかったのですが、Next15では14からいくつかエラーのハンドリング仕様が変わったように見えたので書き留めておきます。
以降はdevelopment modeに限った話であることをご留意ください。(productionは挙動が変わっていないはず...)

予備知識

ErrorBoundaryとonCaughtError

SuspenseとErrorBoundaryはとても便利なReactの機能ですが、Suspenseで発生したエラーをErrorBoundaryで捕らえてハンドリングする際にconsole errorにエラーが表示されてしまっていました。
しかしReact19からはcreateRootにonCaughtError、onUnCaughtErrorというオプションが追加され、ErrorBoundaryでエラーをとらえた(またはとらえられなかった)時の挙動を制御できるようになりました。公式の定義を借りるとそれぞれのオプションの機能は以下の通りです。

onCaughtError: エラーバウンダリ内で React がエラーをキャッチしたときに呼び出されるコールバック。エラーバウンダリにキャッチされた error と、componentStack を含んだ errorInfo を引数にして呼び出されます。
onUncaughtError: エラーがスローされたがエラーバウンダリでキャッチされなかったときに呼び出されるコールバック。スローされた error と、componentStack を含んだ errorInfo を引数にして呼び出されます。

Next15はReact19が公式にサポートされているということで、この仕様も頭の片隅に置いておきましょう。

ReactのWarning

Reactではコンポーネントの使い方に誤りがある時にWarningという名前でconsole errorを吐いています。有名なのはWarning: Each child in a list should have a unique "key" propというWarningでしょう。
前述の通りWarningと言いつつconsole.errorであるということに注意です。

error.stack

V8で生じたエラーはerrorオブジェクトのerror.stackというプロパティでスタックトレースを取得可能です。
普通はそのerrorが生じた箇所を特定するようにErrorを作成すると設定されるのですが、どの箇所で生じたかを意図的に隠したい場合などではerror.stack=nullという形で無理やりnullを詰めることもできます。

Next15でのエラーハンドリングの変更点

前節で軽く触れた予備知識を頭に置いた上で、Next15ではどのようにエラーハンドリングが変わったのかをみていきます。

onCaughtError/onUnCaughtErrorオプションの設定

Next15ではReact19で導入されたonCaughtError/onUnCaughtErrorを早速取り入れています。
https://github.com/vercel/next.js/blob/48eac4d5d14654f148ef1f8168051433eae3faf3/packages/next/src/client/react-client-callbacks/error-boundary-callbacks.ts#L15
ErrorBoundaryでエラーを捕まえた場合のエラーメッセージは、Reactがそれまで出していたもの
The above error occurred in the XX component.
を出すようにしているようですが、追加でhandleClientErrorなる処理をしています。ErrorBoundaryでエラーを捕まえた場合にNextのエラーオーバーレイでも表示するようにした、というわけですね。
Next14以前はSuspense内で発生したエラーはconsole errorにしか出なかったので、Next15以降はオーバーレイだけを見るとエラーが増えたように見えますね。

console.errorに対するパッチ

Next15ではconsole.errorにパッチをあてるようになっており、これはNext14以前では見られなかった機能に思われます。(現時点で見つけられてていない)
https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/globals/intercept-console-error.ts#L14
このパッチにより、console.errorで発生したエラーについてもオーバーレイで表示されるようになっています。このこともNext14からの差異であり、アプリケーション内でconsole.errorを発生させている場合には、オーバーレイ上でエラーが増えたように見えます。
また、このことにより前述のReact Warning(実態はconsole error)もオーバーレイにカウントされるようになります。これまでReact Warningを放置していた人は大量にオーバーレイのエラー数が増える可能性があります。

error.stackがnullでも捕まえる

stackプロパティにはnullを詰めることができるということを前述しました。
しかしこのnullを詰めるやり方はおそらくあまり使われないと思われ、Next14以前ではイベントリスナー内でstackプロパティがnullのものをスルーするようになっていました。
https://github.com/vercel/next.js/blob/v14.2.24/packages/next/src/client/components/react-dev-overlay/internal/helpers/use-error-handler.ts#L35
一方でNext15では(おそらく)この"stackプロパティがnullのものをスルーする"という処理が消えているように見え、実際stackがnullのエラーでもオーバーレイに表示されるようになっています。
万が一stackプロパティがnullのエラーを書いていたらNext15バージョンアップに伴いエラーが多く発生するようになったと見えることでしょう。

まとめ

Next15でのエラーハンドリングについて、気づいた変更点をまとめました。
何気なくバージョンアップしてビルドした際に、オーバーレイ上のエラーの数が以前より増大していることに驚きましたが、一つ一つ見ていくと「アプリ内で発生したエラーはなるべくオーバーレイに出してあげる」というNextの優しさが垣間見えますね。

参考

https://ja.react.dev/reference/react-dom/client/createRoot#error-logging-in-production
https://zenn.dev/uhyo/books/react-19-new/viewer/error-handling
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Error/stack

Discussion