ERR_HTTP2_PROTOCOL_ERROR とは?原因と解決方法

Advertisement
ERR_HTTP2_PROTOCOL_ERROR とは?
ERR_HTTP2_PROTOCOL_ERROR は、ブラウザが プロトコルのルールに違反した HTTP/2 の応答 を受け取ったことを示す Chrome と Edge のエラーです。Chromium 内部ではネットエラー -337 にあたり、「HTTP/2 プロトコルエラーが発生した」と説明されています。Chrome にはこのエラー専用のエラーページがないため、汎用のページが表示されます。「このサイトにアクセスできません。… のウェブページは一時的に停止しているか、新しいウェブアドレスに完全に移動した可能性があります。」というメッセージの下に、ERR_HTTP2_PROTOCOL_ERROR と表示されます。
HTTP/2 は、現在ほとんどの HTTPS サイトが使っている高速版の HTTP です。HTTP/1.1 より厳格で、応答はバイナリのフレームに分割され、ヘッダーは厳密なルールに従い、宣言された応答のサイズは実際に届くデータと一致しなければなりません。ストリームの途中で途切れた応答や禁止されたヘッダーを含む応答など、これらのルールに違反する応答を受け取ると、Chrome は応答全体を不正な形式とみなして破棄します。
開発者は、DevTools のコンソールで net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK) という形でこのエラーを目にすることがよくあります。この組み合わせは有力な手がかりです。サーバーは 200 を返したものの、応答の本文が完全な形で届かなかったことを意味します。
HTTP/2 が不正な形式とみなすもの
HTTP/2 の標準仕様(RFC 9113)には、応答を不正な形式にしてしまう誤りが列挙されています。また、完了前にリセットされたストリームも失敗します。実際に起きるエラーの大半は、次の問題が原因です。
| ルール | 違反の原因 |
|---|---|
| Content-Length は本文のサイズと一致しなければならない | サーバーやプラグインがあるサイズを宣言しながら、別のサイズを送る。たとえば長さを設定した後に出力が圧縮された場合 |
| 応答は正常に終了しなければならない | サーバー、プロキシ、アプリが途中で送信をやめる |
| 接続固有のヘッダーは使えない | HTTP/2 の応答に Connection、Keep-Alive、Proxy-Connection、Transfer-Encoding、Upgrade が含まれている |
| フィールド名は小文字でなければならない | 大文字を含むヘッダー名がそのまま HTTP/2 に渡される |
| 有効なヘッダー値 | ヘッダー値の中に改行やその他の禁止文字が含まれている |
| 有効な :status 行 | ステータスコードが欠落している、または読み取れない |
Advertisement
ERR_HTTP2_PROTOCOL_ERROR の原因
ほとんどのケースはサーバー側が原因ですが、あなた自身のコンピューター上にも、届く途中の応答を壊してしまうものがいくつかあります。
サーバー側: ストリームの途中で途切れた応答(ディスク容量が尽きたか一時ファイルを書き込めないプロキシ、ストリーミング中にクラッシュするアプリ、タイムアウト)、誤った Content-Length の値、禁止されたヘッダーや無効なヘッダー、古いサーバーや CDN の設定にある HTTP/2 対応の不具合。
あなたの側: HTTPS を検査して応答を書き換えるウイルス対策ソフトやファイアウォール、リクエストや応答を変更するブラウザ拡張機能、破損したページのキャッシュ、そしてまれに古いバージョンの Chrome。
解決策1:スーパーリロードとシークレットモードを試す
Ctrl + Shift + R(Mac は Cmd + Shift + R)を押して、キャッシュを使わずに再読み込みします。一度途切れた応答でも、次の試行では問題なく届くことがあります。
次に、シークレット ウィンドウでページを開きます(Ctrl + Shift + N、Mac は Cmd + Shift + N)。シークレットモードには Cookie も通常のプロファイルのキャッシュもなく、拡張機能もデフォルトでオフになっています。そこでページが表示されるなら、通常のウィンドウでは解決策2または解決策3で直せます。
Advertisement
解決策2:そのサイトのキャッシュと Cookie を削除する
破損したキャッシュや肥大化した Cookie があると、特定のサイトでこのエラーが繰り返し発生することがあります。そのサイトのデータだけを削除しましょう。アドレスバーの左端のアイコンをクリック → Cookie とサイトデータ(または サイトの設定)→ データを削除して再読み込みします。より広く削除したい場合は、Ctrl + Shift + Delete を押して、過去数日分の キャッシュされた画像とファイル を削除してください。
解決策3:ウイルス対策ソフトの HTTPS スキャンと拡張機能を一時停止する
HTTPS を復号して検査するセキュリティソフトは、すべての HTTP/2 接続の中間に位置しています。その HTTP/2 の処理に不具合があったり古かったりすると、Chrome が不正な形式とみなす応答をそのまま渡してしまうことがあります。HTTPS スキャン機能だけをオフにして(HTTPS スキャン、Web シールド、SSL/TLS プロトコルフィルタリング、暗号化された接続をスキャンする などの名前が一般的です)、再読み込みしてください。これで直るなら、ウイルス対策ソフトを更新し、そのサイトを除外リストに追加します。
次に、chrome://extensions ですべての拡張機能を無効にして再読み込みし、1つずつ有効に戻してください。広告ブロッカー、プライバシーツール、ヘッダーを編集するものがよくある原因です。
Advertisement
解決策4:Chrome を更新し、他のブラウザでも確認する
chrome://settings/help を開いて保留中の更新をインストールし、ブラウザを再起動します。その後、同じページを Firefox や Safari で開いてみてください。どのブラウザでも失敗するなら、サイトが壊れており、直せるのはサイト管理者だけです。Chrome や Edge だけで失敗する場合も、Chrome が不正な HTTP/2 を最も厳格に拒否するため、たいていはサイト側の問題ですが、解決策2と3をもう一度試す価値はあります。
解決策5:HTTP/2 なしでページをテストする
Chrome は HTTP/2 をオフにした状態で起動できるので、HTTP/2 が原因かどうかを確実に判断できます。まず Chrome のウィンドウをすべて閉じてから、ターミナルで起動します。
# Windows(コマンド プロンプト)
"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-http2
# macOS(ターミナル)
open -a "Google Chrome" --args --disable-http2そのウィンドウでページが表示されるなら、サイトの HTTP/2 の応答が不正な形式になっており、サイト管理者が修正する必要があります。終わったら Chrome を閉じ、通常どおり開き直してください。このフラグはその1回の起動にだけ適用されます。
Advertisement
サイト管理者向け:HTTP/2 プロトコルエラーを直す
異なるネットワークやブラウザの訪問者からこのエラーが報告されている場合、問題はあなたのサーバー環境にあります。次の3つの確認で、ほぼすべての原因を見つけられます。
1. curl で再現する
# HTTP/2:出力の最後に注目する
curl -sv --http2 https://example.com/broken-page -o /dev/null
# 壊れたストリームは次のような行で終わる:
# HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)
# (curl 8.19+: HTTP/2 stream 1 reset by server (error 0x1 PROTOCOL_ERROR))
# 比較のため、同じ URL を HTTP/1.1 で取得する
curl -sv --http1.1 https://example.com/broken-page -o /dev/nullHTTP/1.1 では成功し HTTP/2 では失敗するなら、エラーを確認できたことになります。両者の応答ヘッダーを比較し、ストリームが途切れる前に何バイト届いたかを記録してください。HTTP ヘッダーチェック ツールでも、あなたのネットワークの外からサイトが送っているヘッダーを確認できます。
2. ストリームの途中で途切れた応答を確認する
サーバー側で最も多い原因は、応答が始まった(ステータス 200 とヘッダーが送信された)後に途中で止まってしまうケースです。nginx はアプリからの大きな応答を一時ファイルにバッファリングしますが、ディスクが満杯だったり、nginx が一時フォルダーに書き込めなかったりすると、応答が途中で終わり、ブラウザはプロトコルエラーとして報告します。次を確認してください。
df -h # 満杯のディスクはないか?
sudo grep -E "No space left|Permission denied" /var/log/nginx/error.log | tail
ls -ld /var/lib/nginx/proxy /var/lib/nginx/fastcgi # Debian/Ubuntu の一時ディレクトリ。所有者は nginx のユーザーと一致している必要があるアプリ自体も確認しましょう。大きなページやダウンロードをストリーミング中に PHP や Node のプロセスがクラッシュしたり、タイムアウトしたり、メモリ上限に達したりしても、同じ結果になります。エラーが発生した時刻前後のアプリのログに、たいてい原因が記録されています。
3. Content-Length と禁止ヘッダーを修正する
Content-Length: サーバーに計算させましょう。プラグイン、ミドルウェア、ウェブサーバーが出力を圧縮・変更する場合は、アプリのコードで手動設定しないでください。宣言した長さが実際に送られるバイト数と一致しなくなるからです。WordPress サイトでは、PHP コードで長さを設定しつつ、プラグインや PHP の設定でも出力を圧縮していると、この問題が起こります。
接続固有のヘッダー: 応答に
Connection、Keep-Alive、Transfer-Encoding、Upgradeを設定するコードを削除してください。HTTP/2 ではこれらが禁止されています。nginx はそのほとんどを自動的に取り除きますが、そうしないアプリサーバーやプロキシもあります。ヘッダーの値: どのヘッダーにも改行や制御文字が含まれていないことを確認してください。
Content-Dispositionのファイル名など、ユーザーの入力をヘッダーに入れている場合によく起こります。前段の CDN: Cloudflare などの CDN を使っている場合は、オリジンを直接テストして(curl の
--resolveや hosts ファイルのエントリーを使用)、エラーがオリジンから来ているのか CDN から来ているのかを切り分けます。
ERR_HTTP2_PROTOCOL_ERROR と似たエラーの違い
| エラー | コード | 何が起きたか |
|---|---|---|
| ERR_HTTP2_PROTOCOL_ERROR | -337 | HTTP/2 の応答がプロトコルのルールに違反した |
| ERR_QUIC_PROTOCOL_ERROR | -356 | HTTP/3(QUIC)で起きる同種の失敗 |
| ERR_SSL_PROTOCOL_ERROR | -107 | HTTP/2 が始まる前に HTTPS(TLS)のハンドシェイクが失敗した |
| ERR_CONNECTION_CLOSED | -100 | ページが届く前に接続が閉じられた |
| ERR_EMPTY_RESPONSE | -324 | サーバーが何も送ってこなかった |
詳しいガイド:ERR_QUIC_PROTOCOL_ERROR、ERR_SSL_PROTOCOL_ERROR、ERR_CONNECTION_CLOSED、ERR_EMPTY_RESPONSE。サイトの証明書と HTTPS の設定を外部から確認するには、SSL 証明書チェック を使ってください。
サイトが実際に送っているヘッダーを確認
DNS Robot の HTTP ヘッダーチェックは、当社のサーバーから任意の URL を取得し、ステータスコードとすべての応答ヘッダーを一覧表示します。禁止されたヘッダーや不正な形式のヘッダーを簡単に見つけられます。
試す HTTP ヘッダーチェックAdvertisement
よくある質問
Chrome が、途中で終わった応答、誤ったサイズを宣言した応答、禁止されたヘッダーを含む応答など、プロトコルのルールに違反した HTTP/2 の応答を受け取り、それを破棄したという意味です。Chromium ではネットエラー -337 にあたります。