Invalid WebSocket frame: RSV1 must be clearについての調査ログ
ある日、macOS で開発を行っていると「RangeError: Invalid WebSocket frame: RSV1 must be clear」エラーが表示され、HMR が動作しなくなる事象に遭遇した。
最初は簡単な問題だと思い特に調べずに対応を行ったが、調査が必要になったため、その内容を残す。根本的な解決はしていない。
エラーを見る
次のようなエラーが出力されていた。このエラーはサーバーを立ち上げて直ぐに発生するわけではなく、しばらく経過してから発生し、発生すると HMR が動作しなくなる。
$ vite ➜ Local: http://localhost:8080/
00:00:00 [vite] ws error:RangeError: Invalid WebSocket frame: RSV1 must be clear
エラー自体は非常に分かりやすい。vite が内部的に利用している Node.js の WebSocket 実装として有名なws
でエラーが発生しており、WebSocket がやりとりするデータの形式であるフレームが無効であることを示している。
無効である理由は、エラーから WebSocket のフレームのヘッダの一部である RSV1 がクリア、つまり 0 でないにも関わらず、圧縮メッセージをサポートしていないクライアントに対して送信しているためだと思われる。RSV1 は、圧縮メッセージに対して利用される。
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#format
ポートを使用しているプロセスを見る
何らかのプロセスが、8080 ポートを使用している可能性を考えた。
$ lsof -i:8080
コマンドを実行したが、8080 ポートを使用しているプロセスは見つからなかった。
同様の事例
同様の事例がないか調べると、同じエラーを報告している Issue が複数見つかった。いずれも macOS かつ 8080 ポートを利用しているケースで発生している。
原因だと思われる事象
同様の事例を報告している Issue でも言及されているが、macOS の問題である可能性が高い。 macOS のペアレンタルコントロールなどが 8080 ポートを乗っ取ってしまう問題が報告されている。
解決案
どの Issue でも最終的に macOS では 8080 ポートを使うな、または別のポートを使えという提示がされている。
ws パッケージを直接利用している場合はクラッシュしないようにすれば良いように思うが、vite や webpack などで間接的に利用している場合は対応が難しいと思われる。
現状では、次のような解決案しか考えられない。
- ポートを占有している機能が分かり、問題がなければ無効化する。
- 利用するポートを変更する。
- 修正されている可能性に掛けて、macOS をアップデートする。
- Linux を使う。