ERR_HTTP2_PROTOCOL_ERROR: что значит и как исправить

Advertisement
Что такое ERR_HTTP2_PROTOCOL_ERROR?
ERR_HTTP2_PROTOCOL_ERROR — ошибка Chrome и Edge, которая означает, что браузер получил ответ HTTP/2, нарушающий правила протокола. Внутри Chromium это сетевая ошибка -337: «произошла ошибка протокола HTTP/2». Отдельной страницы ошибки для неё в Chrome нет, поэтому вы видите стандартную: «Не удается получить доступ к сайту» и пояснение, что веб-страница по адресу … временно недоступна или постоянно перемещена по новому адресу, а под ним — ERR_HTTP2_PROTOCOL_ERROR.
HTTP/2 — более быстрая версия HTTP, которой сейчас пользуется большинство HTTPS-сайтов. Она строже, чем HTTP/1.1: ответы разбиваются на двоичные фреймы, заголовки подчиняются точным правилам, а заявленный размер ответа должен совпадать с тем, что реально пришло. Когда Chrome видит ответ, нарушающий эти правила, — например, оборвавшийся на середине или с запрещённым заголовком, — он считает весь ответ некорректным и отбрасывает его.
Разработчики часто видят её в консоли DevTools как net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK). Такое сочетание — сильная подсказка: сервер ответил кодом 200, но тело ответа так и не дошло целым.
Что HTTP/2 считает некорректным
Стандарт HTTP/2 (RFC 9113) перечисляет ошибки, из-за которых ответ считается некорректным, а поток, сброшенный до завершения, тоже приводит к сбою. Вот проблемы, которые стоят за большинством реальных ошибок:
| Правило | Что его нарушает |
|---|---|
| Content-Length должен совпадать с размером тела | Сервер или плагин заявляет один размер, а отправляет другой, например когда вывод сжимается уже после того, как длина была задана |
| Ответ должен корректно завершиться | Сервер, прокси или приложение перестаёт отправлять данные на середине |
| Никаких заголовков, привязанных к соединению | Connection, Keep-Alive, Proxy-Connection, Transfer-Encoding или Upgrade в ответе HTTP/2 |
| Имена полей — только в нижнем регистре | Имена заголовков с заглавными буквами, переданные в HTTP/2 без изменений |
| Допустимые значения заголовков | Переводы строк или другие запрещённые символы внутри значения заголовка |
| Корректная строка :status | Код состояния отсутствует или не читается |
Advertisement
Причины ERR_HTTP2_PROTOCOL_ERROR
Чаще всего причина на стороне сервера, но кое-что на вашем компьютере тоже может повредить ответ по пути к браузеру:
На сервере: ответы, оборванные на середине (прокси, которому не хватило места на диске или который не может записать временные файлы, приложение, упавшее во время отправки, таймаут), неверные значения Content-Length, запрещённые или недопустимые заголовки и ошибки поддержки HTTP/2 в устаревшей конфигурации сервера или CDN.
На вашей стороне: антивирус или файрвол, который проверяет 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 Shield), фильтрация протоколов SSL/TLS или проверка защищённых соединений) и обновите страницу. Если это помогло, обновите антивирус и добавьте исключение для сайта.
Затем отключите все расширения на странице chrome://extensions, обновите страницу и включайте их обратно по одному. Обычно под подозрением блокировщики рекламы, инструменты приватности и всё, что редактирует заголовки.
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 и откройте его снова обычным способом. Флаг действует только на этот один запуск.
Advertisement
Владельцам сайтов: как исправить ошибки протокола HTTP/2
Если об ошибке сообщают посетители из разных сетей и с разными браузерами, проблема в вашем стеке. Эти три проверки находят почти все такие случаи.
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/nullЕсли HTTP/1.1 работает, а HTTP/2 нет, ошибка подтверждена. Сравните заголовки ответа в обоих случаях и отметьте, сколько байт приходит до обрыва потока. Инструмент HTTP Headers тоже показывает, какие заголовки ваш сайт отдаёт при запросе извне вашей сети.
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: пусть его вычисляет сервер. Не задавайте его вручную в коде приложения, если плагин, middleware или веб-сервер тоже сжимают или изменяют вывод: тогда заявленная длина перестаёт совпадать с отправленными байтами. На сайтах 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 | 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 Headers Checker от DNS Robot запрашивает любой URL с наших серверов и показывает код состояния и все заголовки ответа — так запрещённые или некорректные заголовки легко заметить.
Попробовать HTTP Headers CheckerAdvertisement
Часто задаваемые вопросы
Это значит, что Chrome получил ответ HTTP/2, нарушающий правила протокола, — например, оборвавшийся раньше времени, с неверно заявленным размером или с запрещёнными заголовками, — и поэтому отбросил его. В Chromium это сетевая ошибка -337.