ERR_HTTP2_PROTOCOL_ERROR: что значит и как исправить
Ключевой вывод
ERR_HTTP2_PROTOCOL_ERROR (ошибка Chromium -337) означает, что поток HTTP/2 с этой страницей завершился сбоем. Либо сервер, прокси или CDN сбросили его на полпути (Chrome сообщает о любом таком сбросе как о -337), либо Chrome отверг заголовки, нарушающие правила HTTP/2. Посетителям иногда помогает перезагрузка страницы, окно инкогнито, очистка cookie сайта или приостановка проверки HTTPS в антивирусе, но чаще исправить ошибку может только сайт. У владельцев сайтов типичные причины — ответ, который сервер или прокси не смог довести до конца (переполненный диск, недоступная для записи временная папка, падающее приложение), Content-Length, не совпадающий с телом ответа, или запрещённый заголовок вроде Transfer-Encoding. Воспроизведите ошибку командой curl --http2 -v.
Проверьте сейчас

Начать чтение
- Что такое ERR_
HTTP2_ PROTOCOL_ ERROR? - Что HTTP/2 считает некорректным
- Причины ERR_
HTTP2_ PROTOCOL_ ERROR - Решение 1: жёсткая перезагрузка и режим инкогнито
- Решение 2: очистите cookie и кешированные файлы этого сайта
- Решение 3: приостановите проверку HTTPS в антивирусе и расширения
- Решение 4: обновите Chrome и проверьте другие браузеры
- Решение 5: проверьте страницу без HTTP/2
- Владельцам сайтов: как исправить ошибки протокола HTTP/2
- 1. Воспроизведите ошибку с помощью curl
- 2. Проверьте, не обрываются ли ответы на середине
- 3. Исправьте Content-Length и запрещённые заголовки
- ERR_
HTTP2_ PROTOCOL_ ERROR и похожие ошибки: в чём разница - Часто задаваемые вопросы
Что такое ERR_HTTP2_PROTOCOL_ERROR?
ERR_HTTP2_PROTOCOL_ERROR — ошибка Chrome и Edge, которая означает, что поток HTTP/2 с этой страницей завершился сбоем: сервер сбросил его до окончания или прислал заголовки, которые браузер отвергает. В Chromium это сетевая ошибка -337: «There is an HTTP/2 protocol error» (net_error_list.h). Отдельной страницы ошибки для неё в Chrome нет, поэтому вы видите стандартную: «Не удается получить доступ к сайту» и пояснение «Веб-страница по адресу …, возможно, временно недоступна или постоянно перемещена по новому адресу», а под ним — ERR_HTTP2_PROTOCOL_ERROR. Edge показывает тот же код на собственном экране «Hmm… can't reach this page».
HTTP/2 — более быстрая версия HTTP, которой сейчас пользуется большинство HTTPS-сайтов. Каждый запрос идёт отдельным потоком внутри одного соединения, и любая из сторон может отменить поток сбросом. Chrome сообщает о любом сбросе со стороны сервера как об ошибке протокола, какой бы ни была причина сброса, а ещё сам отменяет поток, если заголовки нарушают правила HTTP/2 (заголовок Transfer-Encoding, заглавные буквы в имени заголовка, отсутствующий статус).
Разработчики часто видят её в консоли DevTools как net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK). Такое сочетание — сильная подсказка: заголовки были корректными и сервер ответил 200, но поток оборвался, пока приходило тело ответа.
Посмотрите, какие заголовки страница отдаёт на самом деле
Что HTTP/2 считает некорректным
Стандарт HTTP/2 (RFC 9113) перечисляет ошибки, из-за которых ответ считается некорректным. Это проблемы, которые стоят за большинством реальных ошибок, и вот как каждая из них доходит до браузера:
| Правило | Что его нарушает |
|---|---|
| Content-Length должен совпадать с размером тела | Сервер или плагин заявляет один размер, а отправляет другой; стоящие перед ним прокси, CDN или сервер сбрасывают поток |
| Ответ должен корректно завершиться | Сервер, прокси или приложение не может закончить ответ (переполненный диск, сбой, таймаут) и сбрасывает поток; так делает nginx, если не может дописать уже начатый ответ |
| Никаких заголовков, привязанных к соединению | Transfer-Encoding в ответе HTTP/2 (Chrome его отвергает); Connection, Keep-Alive, Proxy-Connection и Upgrade тоже запрещены, и строгие клиенты вроде curl их отвергают |
| Имена полей — только в нижнем регистре | Имена заголовков с заглавными буквами, переданные в HTTP/2 без изменений |
| Допустимые значения заголовков | Переводы строк или другие запрещённые символы внутри значения заголовка |
| Корректная строка :status | Код состояния отсутствует или не читается |
Причины ERR_HTTP2_PROTOCOL_ERROR
Чаще всего причина на стороне сервера, но кое-что на вашем компьютере тоже может повредить ответ по пути к браузеру:
- На сервере: ответ, который сервер или прокси не может довести до конца (прокси, у которого закончилось место на диске или который не может записать временные файлы, приложение, упавшее во время отправки, таймаут), неверные значения Content-Length, из-за которых стоящий перед сервером прокси сдаётся, запрещённые или недопустимые заголовки и ошибки поддержки HTTP/2 в устаревшей конфигурации сервера или CDN.
- На вашей стороне: антивирус или файрвол, который проверяет 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 Shield → «Enable HTTPS scanning»; ESET: «SSL/TLS protocol filtering»; Kaspersky: «Scan encrypted connections») и обновите страницу. Если это помогло, обновите антивирус и добавьте исключение для сайта.
Затем отключите все расширения на странице chrome://extensions, обновите страницу и включайте их обратно по одному. Обычно под подозрением блокировщики рекламы, инструменты приватности и всё, что редактирует заголовки.
Решение 4: обновите Chrome и проверьте другие браузеры
Откройте chrome://settings/help, чтобы установить ожидающее обновление, и перезапустите браузер. Затем откройте ту же страницу в Firefox или Safari, а также на другом устройстве или в другой сети. Если она не работает нигде, сайт сломан, и исправить его может только владелец (проверка HTTPS в антивирусе влияет на все браузеры на одном компьютере, поэтому настоящий тест — второе устройство). Если ошибка только в Chrome или Edge, сайт, вероятно, отправляет заголовок, который Chrome отвергает; решения 2 и 3 всё равно стоит повторить.
Решение 5: проверьте страницу без HTTP/2
Chrome можно запустить с выключенными HTTP/2 (и HTTP/3) — так видно, замешан ли HTTP/2. Запустите из терминала второй, отдельный Chrome; дополнительная папка профиля делает его новым экземпляром, даже если обычный Chrome открыт:
# 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
Если об ошибке сообщают посетители из разных сетей и с разными браузерами, проблема в вашем стеке. Эти три проверки находят почти все такие случаи.
1. Воспроизведите ошибку с помощью curl
# 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 (он отвергает несовпадение Content-Length и заголовки соединения, которые Chrome пропускает), так что считайте это сильной подсказкой, а не доказательством. Проверка HTTP-заголовков показывает, какие заголовки задаёт ваше приложение, если смотреть снаружи вашей сети.
2. Проверьте, не обрываются ли ответы на середине
Самая частая серверная причина — ответ, который начался (статус 200, заголовки отправлены), а потом не может быть завершён. nginx буферизует крупные ответы вашего приложения во временные файлы, и если диск переполнен или nginx не может писать в свою временную папку, он сбрасывает поток, а браузер сообщает об ошибке протокола. Проверьте:
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: пусть его вычисляет сервер. Не задавайте его вручную в коде приложения, если плагин, middleware или веб-сервер тоже сжимают или изменяют вывод: тогда заявленная длина перестаёт совпадать с отправленными байтами. На сайтах WordPress так бывает, когда длина задаётся в PHP-коде, а плагин или настройка PHP дополнительно сжимает вывод.
- 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 | -337 | Ответ HTTP/2 нарушил правила протокола |
| ERR_QUIC_PROTOCOL_ERROR | -356 | Такой же сбой, но по HTTP/3 (QUIC) |
| ERR_SSL_PROTOCOL_ERROR | -107 | HTTPS-рукопожатие (TLS) не удалось ещё до начала HTTP/2 |
| ERR_CONNECTION_CLOSED | -100 | Соединение закрылось до того, как пришла страница |
| ERR_EMPTY_RESPONSE | -324 | Сервер вообще ничего не отправил |
Подробные руководства: ERR_QUIC_PROTOCOL_ERROR, ERR_SSL_PROTOCOL_ERROR, ERR_CONNECTION_CLOSED и ERR_EMPTY_RESPONSE. Чтобы проверить сертификат сайта и настройку HTTPS извне, воспользуйтесь SSL Checker.
Посмотрите, какие заголовки на самом деле отдаёт ваш сайт
Проверка HTTP-заголовков от DNS Robot запрашивает любой URL с наших серверов по HTTP/1.1 и показывает код состояния и каждый заголовок ответа, который задаёт ваше приложение (Content-Length, Content-Encoding, Content-Disposition), чтобы вы могли сравнить их с тем, что показывает curl --http2.
Источники
- net_error_list.h (HTTP2_PROTOCOL_ERROR -337), Chromium
- RFC 9113: HTTP/2, malformed messages, IETF
- HTTP/2: ERR_HTTP2_PROTOCOL_ERROR, Cloudflare


