ERR_HTTP2_PROTOCOL_ERROR とは?原因と解決方法

ポイント

ERR_HTTP2_PROTOCOL_ERROR(Chromium のエラー -337)は、ページを運ぶ HTTP/2 ストリームが失敗したことを示します。サーバー、プロキシ、CDN が途中でストリームをリセットしたか(Chrome はこの種のリセットをすべて -337 として報告します)、HTTP/2 のルールに反するヘッダーを Chrome が拒否したかのどちらかです。訪問者側では、再読み込み、シークレットウィンドウ、そのサイトの Cookie の削除、ウイルス対策ソフトの HTTPS スキャンの一時停止で通ることもありますが、多くはサイト側でしか直せません。サイト運営者側の主な原因は、サーバーやプロキシが最後まで返せなかった応答(ディスクの空き容量不足、書き込めない一時フォルダ、アプリのクラッシュ)、本文と一致しない Content-Length、Transfer-Encoding のような禁止ヘッダーです。curl --http2 -v で再現できます。

今すぐ確認

ERR_HTTP2_PROTOCOL_ERROR が表示された Chrome のエラーページと、HTTP/2 プロトコルエラーを直すための確認項目
ERR_HTTP2_PROTOCOL_ERROR が表示された Chrome のエラーページと、HTTP/2 プロトコルエラーを直すための確認項目
読み始める
  1. ERR_HTTP2_PROTOCOL_ERROR とは?
  2. HTTP/2 が不正な形式とみなすもの
  3. ERR_HTTP2_PROTOCOL_ERROR の原因
  4. 解決策1:スーパーリロードとシークレットモードを試す
  5. 解決策2:そのサイトの Cookie とキャッシュを削除する
  6. 解決策3:ウイルス対策ソフトの HTTPS スキャンと拡張機能を一時停止する
  7. 解決策4:Chrome を更新し、他のブラウザでも確認する
  8. 解決策5:HTTP/2 なしでページをテストする
  9. サイト管理者向け:HTTP/2 プロトコルエラーを直す
  10. 1. curl で再現する
  11. 2. ストリームの途中で途切れた応答を確認する
  12. 3. Content-Length と禁止ヘッダーを修正する
  13. ERR_HTTP2_PROTOCOL_ERROR と似たエラーの違い
  14. よくある質問

ERR_HTTP2_PROTOCOL_ERROR とは?

ERR_HTTP2_PROTOCOL_ERROR は、ページを運ぶ HTTP/2 ストリームが失敗したことを示す Chrome と Edge のエラーです。サーバーが完了前にストリームをリセットしたか、ブラウザが拒否するヘッダーを送ったことを意味します。Chromium 内部ではネットエラー -337 にあたり、「There is an HTTP/2 protocol error」と説明されています(net_error_list.h)。Chrome にはこのエラー専用のエラーページがないため、汎用のページが表示されます。「このサイトにアクセスできません。… のウェブページは一時的に停止しているか、新しいウェブアドレスに移動した可能性があります。」というメッセージの下に、ERR_HTTP2_PROTOCOL_ERROR と表示されます。Edge も独自のエラー画面に同じコードを表示します。

HTTP/2 は、現在ほとんどの HTTPS サイトが使っている高速版の HTTP です。各リクエストは 1 本の接続の中で独立したストリームとして流れ、どちらの側もリセットでストリームを取り消せます。Chrome はサーバーからのリセットを、サーバー側の理由にかかわらずプロトコルエラーとして報告します。また、ヘッダーが HTTP/2 のルールに反している場合(Transfer-Encoding ヘッダー、ヘッダー名の大文字、ステータスの欠落など)は、Chrome 自身がストリームを取り消します。

開発者は DevTools のコンソールで net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK) という形でよく目にします。この組み合わせは強い手がかりです。ヘッダーは正しく、サーバーは 200 を返しましたが、本文が届いている途中でストリームが失敗したことを示しています。

ページが実際に送っているヘッダーを確認する

HTTP/2 が不正な形式とみなすもの

HTTP/2 の標準規格(RFC 9113)は、応答を不正な形式にする誤りを列挙しています。実際のエラーの大半はこれらの問題が原因で、それぞれがブラウザに届く仕組みは次のとおりです。

ルール違反する例
Content-Length は本文のサイズと一致していなければならないサーバーやプラグインが宣言したサイズと実際に送ったサイズが違う。手前のプロキシ、CDN、サーバーがストリームをリセットする
応答はきれいに終わらなければならないサーバー、プロキシ、アプリが応答を完了できず(ディスクの空き容量不足、クラッシュ、タイムアウト)、ストリームをリセットする。nginx は、開始済みの応答を完了できないときにこれを行う
接続固有のヘッダーは禁止HTTP/2 の応答に含まれる Transfer-Encoding(Chrome は拒否)。Connection、Keep-Alive、Proxy-Connection、Upgrade も禁止で、curl のような厳格なクライアントは拒否する
フィールド名は小文字でなければならない大文字を含むヘッダー名が、そのまま HTTP/2 に渡される
有効なヘッダー値ヘッダー値の中の改行やその他の禁止文字
有効な :status 擬似ヘッダーステータスコードの欠落や判読不能

ERR_HTTP2_PROTOCOL_ERROR の原因

ほとんどのケースはサーバー側が原因ですが、あなた自身のコンピューター上にも、届く途中の応答を壊してしまうものがいくつかあります。

  • サーバー側: サーバーやプロキシが最後まで返せない応答(ディスク容量が尽きた、または一時ファイルを書き込めないプロキシ、ストリーミング中にクラッシュするアプリ、タイムアウト)、手前のプロキシが諦める原因になる誤った Content-Length の値、禁止された、または無効なヘッダー、古いサーバーや CDN 設定での HTTP/2 サポートの不具合。
  • 利用者側: HTTPS を検査して通信を書き換えるウイルス対策ソフトやファイアウォール、リクエストやレスポンスを変更するブラウザ拡張機能、サーバーが正しく処理できないリクエスト(たとえば大きすぎる Cookie)、そしてまれに古い Chrome のバージョン。

解決策1:スーパーリロードとシークレットモードを試す

Ctrl + Shift + R(Mac は Cmd + Shift + R)を押して、キャッシュを使わずに再読み込みします。一度途切れた応答でも、次の試行では問題なく届くことがあります。

次に、シークレット ウィンドウでページを開きます(Ctrl + Shift + N、Mac は Cmd + Shift + N)。シークレットモードには Cookie も通常のプロファイルのキャッシュもなく、拡張機能もデフォルトでオフになっています。そこでページが表示されるなら、通常のウィンドウでは解決策2または解決策3で直せます。

解決策2:そのサイトの Cookie とキャッシュを削除する

サイトの Cookie とキャッシュを削除すると、Chrome が送るリクエストが変わり(Cookie が減り、再検証するキャッシュもなくなり)、サーバー側の不具合を回避できることがあります。アドレスバーの左にある サイト情報を表示 をクリック → Cookie とサイトデータ → デバイス上のサイトデータを管理 → 削除して再読み込みします。より広く削除したい場合は、Ctrl + Shift + Delete を押して、過去 7 日間 の キャッシュされた画像とファイル を削除してください。

解決策3:ウイルス対策ソフトの HTTPS スキャンと拡張機能を一時停止する

HTTPS を復号して検査するセキュリティソフトは、すべての HTTP/2 接続の中間に位置しています。その HTTP/2 の処理に不具合があったり古かったりすると、ストリームを壊したり、Chrome が拒否するヘッダーをそのまま渡してしまったりすることがあります。HTTPS スキャン機能だけをオフにして(Avast/AVG:Web シールド → Enable HTTPS scanning、ESET:SSL/TLS プロトコルフィルタリング、Kaspersky:暗号化された接続をスキャンする)、再読み込みしてください。これで直るなら、ウイルス対策ソフトを更新し、そのサイトを除外リストに追加します。

次に、chrome://extensions ですべての拡張機能を無効にして再読み込みし、1 つずつ有効に戻していきます。広告ブロッカー、プライバシー系ツール、ヘッダーを編集するものが典型的な原因です。

解決策4:Chrome を更新し、他のブラウザでも確認する

chrome://settings/help を開いて保留中の更新をインストールし、ブラウザを再起動します。その後、同じページを Firefox や Safari で、さらに別の端末やネットワークでも開いてみてください。どこでも失敗するなら、サイト自体が壊れており、直せるのは運営者だけです(ウイルス対策ソフトの HTTPS スキャンは 1 台のパソコン上のすべてのブラウザに影響するため、2 台目の端末が本当のテストになります)。Chrome や Edge だけが失敗する場合、サイトが Chrome の拒否するヘッダーを送っている可能性が高いですが、解決策2と3をもう一度試す価値はあります。

解決策5:HTTP/2 なしでページをテストする

Chrome は HTTP/2(と HTTP/3)をオフにして起動でき、HTTP/2 が関係しているかどうかを確認できます。ターミナルから 2 つ目の別の Chrome を起動します。追加のプロファイルフォルダを指定すると、通常の Chrome が開いたままでも新しいインスタンスになります。

bash
# Windows (Command Prompt)
"C:\Program Files\Google\Chrome\Application\chrome.exe" --user-data-dir="%TEMP%\h2test" --disable-http2 --disable-quic

# macOS (Terminal)
open -na "Google Chrome" --args --user-data-dir=/tmp/h2test --disable-http2 --disable-quic

そのウィンドウでページが読み込まれるなら、HTTP/2 の応答が問題であり、運営者が修正する必要があります。ERR_CONTENT_LENGTH_MISMATCH や ERR_INCOMPLETE_CHUNKED_ENCODING で失敗するようになった場合は、プロトコルにかかわらずサーバーが応答を途中で切っています。終わったらそのウィンドウを閉じてください。通常の Chrome には影響しません。

サイト管理者向け:HTTP/2 プロトコルエラーを直す

異なるネットワークやブラウザの訪問者からこのエラーが報告されている場合、問題はあなたのサーバー環境にあります。次の3つの確認で、ほぼすべての原因を見つけられます。

1. curl で再現する

bash
# HTTP/2: watch the end of the output
curl -sv --http2 https://example.com/broken-page -o /dev/null
# A stream the server gave up on ends with something like:
# HTTP/2 stream 1 was not closed cleanly: INTERNAL_ERROR (err 2)
# (curl 8.19+: HTTP/2 stream 1 reset by server (error 0x2 INTERNAL_ERROR);
#  "reset by curl" means curl rejected the response itself)

# Same URL over HTTP/1.1 for comparison
curl -sv --http1.1 https://example.com/broken-page -o /dev/null

HTTP/1.1 では動いて HTTP/2 では失敗するなら、HTTP/2 が関係しています。「Reset by server」は、サーバーまたはプロキシが応答の途中で諦めたことを示します。curl は Chrome とまったく同じ項目を検査するわけではない(Chrome が通す Content-Length の不一致や接続ヘッダーを curl は拒否します)ため、証拠ではなく強い手がかりとして扱ってください。HTTP ヘッダーチェッカーでは、アプリが設定しているヘッダーをネットワークの外側から確認できます。

2. ストリームの途中で途切れた応答を確認する

サーバー側で最も多い原因は、始まったのに(ステータス 200、ヘッダー送信済み)最後まで完了できない応答です。nginx はアプリからの大きめの応答を一時ファイルにバッファリングするため、ディスクがいっぱいだったり、nginx が一時フォルダに書き込めなかったりすると、ストリームをリセットし、ブラウザはプロトコルエラーを報告します。次を確認してください。

bash
df -h                                   # is any disk full?
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 packages
ls -ld /var/cache/nginx/proxy_temp /var/cache/nginx/fastcgi_temp   # nginx.org packages
# the temp folders must be writable by the nginx worker user

アプリ自体も確認しましょう。大きなページやダウンロードをストリーミング中に PHP や Node のプロセスがクラッシュしたり、タイムアウトしたり、メモリ上限に達したりしても、同じ結果になります。エラーが発生した時刻前後のアプリのログに、たいてい原因が記録されています。

3. Content-Length と禁止ヘッダーを修正する

  • Content-Length: サーバーに計算させましょう。プラグイン、ミドルウェア、Web サーバーも出力を圧縮・変更する場合は、アプリのコードで手動設定しないでください。宣言した長さが実際に送ったバイト数と一致しなくなるためです。PHP のコードで長さを設定しつつ、プラグインや PHP の設定も出力を圧縮している状態は、WordPress サイトでこれが起きる原因の一つです。
  • Transfer-Encoding: HTTP/2 の応答では絶対に送らないでください。Chrome は見つけた時点でストリームをリセットします。RFC 9113 は Connection、Keep-Alive、Proxy-Connection、Upgrade も禁止しています。Chrome はこれらを無視しますが、curl などの厳格なクライアントは拒否し、nginx はプロキシ経由の応答からほとんどを自動的に取り除きます。
  • ヘッダー値: どのヘッダーにも改行や制御文字が含まれていないことを確認してください。Content-Disposition のファイル名のように、ユーザー入力がそのままヘッダーに入ることが原因になりがちです。
  • 手前の CDN: Cloudflare などの CDN を使っている場合は、オリジンを直接テストして(curl の --resolve や hosts エントリを使用)、エラーの出どころがオリジンか CDN かを切り分けます。

ERR_HTTP2_PROTOCOL_ERROR と似たエラーの違い

エラーコード何が起きたか
ERR_HTTP2_PROTOCOL_ERROR-337HTTP/2 の応答がプロトコルのルールに違反した
ERR_QUIC_PROTOCOL_ERROR-356HTTP/3(QUIC)で起きる同種の失敗
ERR_SSL_PROTOCOL_ERROR-107HTTP/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 ヘッダーチェッカーは、当社のサーバーから HTTP/1.1 で任意の URL を取得し、ステータスコードとアプリが設定しているすべてのレスポンスヘッダー(Content-Length、Content-Encoding、Content-Disposition)を一覧表示します。curl --http2 の出力と比較できます。

出典

  1. net_error_list.h(HTTP2_PROTOCOL_ERROR -337), Chromium
  2. RFC 9113:HTTP/2、不正な形式のメッセージ, IETF
  3. HTTP/2:ERR_HTTP2_PROTOCOL_ERROR, Cloudflare

よくある質問

ERR_HTTP2_PROTOCOL_ERROR とはどういう意味ですか?

ページを運ぶ HTTP/2 ストリームが失敗したという意味です。多くの場合、サーバー、プロキシ、CDN が応答の完了前にストリームをリセットし、Chrome がそれをプロトコルエラーとして報告します。ときには、Transfer-Encoding など HTTP/2 が禁止するヘッダーを Chrome が拒否した場合もあります。Chromium ではネットエラー -337 です。

ERR_HTTP2_PROTOCOL_ERROR は自分のせいですか、それともウェブサイト側の問題ですか?

多くはサイト側の問題です。ウイルス対策ソフトの HTTPS スキャン、ブラウザ拡張機能、大きすぎる Cookie が原因になることもあるため、まずスーパーリロード、シークレットウィンドウ、HTTPS スキャンの一時停止を試してください。すべてのブラウザとすべてのネットワークで失敗するなら、直せるのはサイト運営者だけです。

net::ERR_HTTP2_PROTOCOL_ERROR 200 とはどういう意味ですか?

ヘッダーは正しく、サーバーは 200 を返しましたが、本文が届いている途中でストリームが失敗した状態です。サーバー、プロキシ、CDN が途中でリセットしています。よくある原因は、ディスク容量が尽きた、または一時ファイルを書き込めなかったプロキシ、応答の途中でクラッシュしたアプリ、本文と一致しない Content-Length です。

Chrome で ERR_HTTP2_PROTOCOL_ERROR を直すには?

Ctrl + Shift + R でスーパーリロードし、シークレットモードを試し、そのサイトの Cookie とキャッシュを削除し、ウイルス対策ソフトの HTTPS スキャンを一時停止し、拡張機能を無効にして、Chrome を更新します。HTTP/2 が関係しているか確認するには、--user-data-dir、--disable-http2、--disable-quic を付けた別の Chrome を起動して、ページが読み込まれるか確かめてください。

Chrome で HTTP/2 を無効にできますか?

設定ページからはできません。テストする場合は、--disable-http2 と --disable-quic を付けた別の Chrome を起動します(--user-data-dir も付けないと、起動中の Chrome がフラグを無視します)。その起動にのみ有効です。HTTP/2 はサイトを高速にするため、これは診断用であり、長期的な解決策ではありません。

nginx のサイトで ERR_HTTP2_PROTOCOL_ERROR が出るのはなぜですか?

ディスクがいっぱいでないか、nginx がプロキシや FastCGI の一時フォルダに書き込めるか(エラーログで「No space left on device」や「Permission denied」を探します)、アプリが応答の途中でクラッシュしていないか、アプリが Transfer-Encoding ヘッダーや誤った Content-Length を送っていないかを確認してください。curl --http2 -v で再現できます。

Cloudflare が原因で ERR_HTTP2_PROTOCOL_ERROR が出ることはありますか?

たいていの場合、原因はオリジン側にあります。Cloudflare のドキュメントは、不正な形式のオリジンヘッダーと圧縮の問題(Content-Length が更新されていない gzip 本文、または壊れた gzip)をよくある原因として挙げており、Cloudflare 経由のときだけ表れることもあります。Cloudflare を通さず、オリジンを直接テストしてください。

ERR_HTTP2_PROTOCOL_ERROR と ERR_QUIC_PROTOCOL_ERROR の違いは何ですか?

異なるプロトコルで起きる同種の失敗です。ERR_HTTP2_PROTOCOL_ERROR は HTTP/2(TCP 上)で、ERR_QUIC_PROTOCOL_ERROR は HTTP/3(QUIC 上)で発生します。後者では、QUIC に干渉するファイアウォールやウイルス対策ソフトもよくある原因です。

キャッシュを削除すれば ERR_HTTP2_PROTOCOL_ERROR は直りますか?

効く場合もあります。サイトの Cookie とキャッシュを削除すると Chrome が送るリクエストが変わり、サーバー側の不具合を回避できることがあるので、試す価値はあります。サーバーがストリームをリセットし続けたり不正なヘッダーを送り続けたりする場合は、サイトが修正されるまでエラーが再発します。

著者について

Shaik Vahid

DNS Robot 創設者. Vahid は長年 Web ホスティングのサポートで、お客様のドメイン、DNS レコード、SSL 証明書、メール配信の問題を解決してきました。DNS Robot のツールを開発し、実際によく起きるエラーをもとにこれらのガイドを書いています。

HTTPヘッダーチェッカー

HTTPレスポンスヘッダーとセキュリティヘッダーのグレーディング分析