ERR_HTTP2_PROTOCOL_ERROR: nguyên nhân và cách khắc phục
Điểm chính
ERR_HTTP2_PROTOCOL_ERROR (mã lỗi Chromium -337) nghĩa là luồng HTTP/2 chứa trang đã thất bại. Hoặc máy chủ, proxy hay CDN đã reset luồng giữa chừng (Chrome báo mọi lần reset như vậy là -337), hoặc Chrome từ chối các header vi phạm quy tắc HTTP/2. Với người truy cập, tải lại trang, mở cửa sổ Ẩn danh, xóa cookie của trang hoặc tạm dừng quét HTTPS của phần mềm diệt virus đôi khi vượt qua được lỗi, nhưng thường chỉ chính trang web mới sửa được. Với chủ trang web, nguyên nhân thường gặp là phản hồi mà máy chủ hoặc proxy không hoàn tất được (đầy ổ đĩa, thư mục tạm không ghi được, ứng dụng bị crash), Content-Length không khớp với phần thân, hoặc header bị cấm như Transfer-Encoding. Hãy tái hiện lỗi bằng curl --http2 -v.
Kiểm tra ngay

Bắt đầu đọc
- ERR_
HTTP2_ PROTOCOL_ ERROR là gì? - Những gì HTTP/2 coi là sai định dạng
- Nguyên nhân gây ra lỗi ERR_
HTTP2_ PROTOCOL_ ERROR - Cách 1: tải lại cứng và thử chế độ ẩn danh
- Cách 2: xóa cookie và tệp đã lưu của trang web đó
- Cách 3: tạm dừng quét HTTPS của phần mềm diệt virus và tiện ích mở rộng
- Cách 4: cập nhật Chrome và kiểm tra trên trình duyệt khác
- Cách 5: kiểm tra trang khi không dùng HTTP/2
- Dành cho chủ website: khắc phục lỗi giao thức HTTP/2
- 1. Tái hiện lỗi bằng curl
- 2. Kiểm tra phản hồi bị cắt giữa chừng
- 3. Sửa Content-Length và các header bị cấm
- ERR_
HTTP2_ PROTOCOL_ ERROR khác gì các lỗi tương tự - Câu hỏi thường gặp
ERR_HTTP2_PROTOCOL_ERROR là gì?
ERR_HTTP2_PROTOCOL_ERROR là lỗi trên Chrome và Edge, cho biết luồng HTTP/2 chứa trang đã thất bại: máy chủ đã reset luồng trước khi hoàn tất hoặc gửi các header mà trình duyệt từ chối. Trong Chromium, đây là mã lỗi mạng -337: "There is an HTTP/2 protocol error" (net_error_list.h). Chrome không có trang lỗi riêng cho nó, nên bạn sẽ thấy trang chung: "Không thể truy cập trang web này" cùng dòng "Trang web tại … có thể tạm thời không hoạt động hay được chuyển vĩnh viễn sang địa chỉ web mới", với ERR_HTTP2_PROTOCOL_ERROR bên dưới. Edge hiển thị cùng mã lỗi trên màn hình riêng của nó, "Hmm… can't reach this page".
HTTP/2 là phiên bản HTTP nhanh hơn mà hầu hết các trang HTTPS hiện nay đều sử dụng. Mỗi yêu cầu đi trong một luồng (stream) riêng bên trong một kết nối duy nhất, và cả hai phía đều có thể hủy một luồng bằng cách reset. Chrome báo mọi lần reset từ máy chủ là lỗi giao thức, bất kể lý do reset là gì, và tự hủy luồng khi header vi phạm quy tắc của HTTP/2 (header Transfer-Encoding, chữ in hoa trong tên header, thiếu trạng thái).
Lập trình viên thường thấy lỗi này trong console của DevTools dưới dạng net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK). Sự kết hợp đó là một manh mối rõ ràng: header hợp lệ và máy chủ đã trả lời 200, nhưng luồng bị lỗi trong lúc phần thân đang đến.
Xem các header mà một trang thực sự gửi
Những gì HTTP/2 coi là sai định dạng
Chuẩn HTTP/2 (RFC 9113) liệt kê các lỗi khiến một phản hồi bị coi là sai định dạng. Đây là những vấn đề đứng sau hầu hết các lỗi trong thực tế, cùng cách mỗi lỗi đến được trình duyệt:
| Quy tắc | Điều gì vi phạm nó |
|---|---|
| Content-Length phải bằng kích thước phần thân | Máy chủ hoặc plugin khai báo một kích thước nhưng gửi kích thước khác; proxy, CDN hoặc máy chủ đứng trước sẽ reset luồng |
| Phản hồi phải kết thúc gọn gàng | Máy chủ, proxy hoặc ứng dụng không hoàn tất được phản hồi (đầy ổ đĩa, crash, hết thời gian chờ) và reset luồng; nginx làm vậy khi không thể hoàn tất một phản hồi đã bắt đầu |
| Không có header dành riêng cho kết nối | Transfer-Encoding trong phản hồi HTTP/2 (Chrome từ chối); Connection, Keep-Alive, Proxy-Connection và Upgrade cũng bị cấm, và các client nghiêm ngặt như curl từ chối chúng |
| Tên trường phải viết thường | Tên header có chữ in hoa được chuyển thẳng sang HTTP/2 |
| Giá trị header hợp lệ | Ký tự xuống dòng hoặc ký tự bị cấm khác bên trong giá trị header |
| Dòng :status hợp lệ | Mã trạng thái bị thiếu hoặc không đọc được |
Nguyên nhân gây ra lỗi ERR_HTTP2_PROTOCOL_ERROR
Hầu hết các trường hợp đến từ phía máy chủ, nhưng một vài thứ trên chính máy tính của bạn cũng có thể làm hỏng phản hồi trên đường đến:
- Trên máy chủ: phản hồi mà máy chủ hoặc proxy không hoàn tất được (proxy hết dung lượng ổ đĩa hoặc không ghi được tệp tạm, ứng dụng bị crash khi đang truyền dữ liệu, hết thời gian chờ), giá trị Content-Length sai khiến proxy phía trước bỏ cuộc, header bị cấm hoặc không hợp lệ, và hỗ trợ HTTP/2 bị lỗi trong cấu hình máy chủ hoặc CDN cũ.
- Ở phía bạn: phần mềm diệt virus hoặc tường lửa kiểm tra HTTPS và viết lại lưu lượng, tiện ích mở rộng của trình duyệt sửa đổi yêu cầu hoặc phản hồi, một yêu cầu mà máy chủ xử lý sai (ví dụ cookie quá lớn), và đôi khi là phiên bản Chrome đã lỗi thời.
Cách 1: tải lại cứng và thử chế độ ẩn danh
Nhấn Ctrl + Shift + R (Mac: Cmd + Shift + R) để tải lại mà không dùng bộ nhớ đệm. Một phản hồi bị cắt một lần có thể đến bình thường trong lần thử tiếp theo.
Sau đó mở trang trong cửa sổ Ẩn danh (Ctrl + Shift + N, Mac Cmd + Shift + N). Chế độ Ẩn danh không có cookie, không có bộ nhớ đệm từ hồ sơ thông thường của bạn, và tiện ích mở rộng mặc định bị tắt. Nếu trang tải được ở đó, Cách 2 hoặc Cách 3 sẽ giải quyết vấn đề trong cửa sổ thông thường.
Cách 2: xóa cookie và tệp đã lưu của trang web đó
Xóa cookie và tệp đã lưu của trang sẽ thay đổi yêu cầu mà Chrome gửi đi (ít cookie hơn, không có bản sao trong bộ nhớ đệm để xác thực lại), và có thể né được lỗi của máy chủ. Nhấp vào biểu tượng Xem thông tin trang web ở bên trái thanh địa chỉ → Cookie và dữ liệu trang web → Quản lý dữ liệu trang web trên thiết bị → xóa dữ liệu, rồi tải lại. Để dọn dẹp rộng hơn, nhấn Ctrl + Shift + Delete và xóa Tệp và hình ảnh được lưu trong bộ nhớ đệm trong khoảng 7 ngày qua.
Cách 3: tạm dừng quét HTTPS của phần mềm diệt virus và tiện ích mở rộng
Phần mềm bảo mật giải mã và kiểm tra HTTPS nằm ở giữa mọi kết nối HTTP/2. Nếu cách nó xử lý HTTP/2 bị lỗi hoặc đã lỗi thời, nó có thể làm hỏng luồng hoặc chuyển tiếp những header mà Chrome từ chối. Chỉ tắt tính năng quét HTTPS (Avast/AVG: Web Shield → "Enable HTTPS scanning"; ESET: "SSL/TLS protocol filtering"; Kaspersky: "Scan encrypted connections") rồi tải lại. Nếu cách đó khắc phục được, hãy cập nhật phần mềm diệt virus và thêm ngoại lệ cho trang web.
Tiếp theo, tắt tất cả tiện ích mở rộng tại chrome://extensions, tải lại, rồi bật lại từng cái một. Trình chặn quảng cáo, công cụ bảo vệ quyền riêng tư và bất cứ thứ gì chỉnh sửa header là những nghi phạm thường gặp.
Cách 4: cập nhật Chrome và kiểm tra trên trình duyệt khác
Mở chrome://settings/help để cài đặt bản cập nhật đang chờ, sau đó khởi động lại trình duyệt. Rồi mở cùng trang đó trên Firefox hoặc Safari, cũng như trên một thiết bị hoặc mạng khác. Nếu trang lỗi ở mọi nơi, trang web đang bị hỏng và chỉ chủ trang mới khắc phục được (quét HTTPS của phần mềm diệt virus ảnh hưởng đến mọi trình duyệt trên cùng một máy, nên phép thử thực sự là thiết bị thứ hai). Nếu chỉ Chrome hoặc Edge bị lỗi, nhiều khả năng trang web đang gửi một header mà Chrome từ chối; Cách 2 và Cách 3 vẫn đáng để thử lại.
Cách 5: kiểm tra trang khi không dùng HTTP/2
Chrome có thể được khởi động với HTTP/2 (và HTTP/3) bị tắt, giúp bạn biết HTTP/2 có liên quan hay không. Hãy khởi động một Chrome thứ hai, riêng biệt từ terminal; thư mục hồ sơ bổ sung khiến nó trở thành một phiên bản mới ngay cả khi Chrome thông thường của bạn đang mở:
# 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-quicNếu trang tải được trong cửa sổ đó, phản hồi HTTP/2 của trang web đang có vấn đề và chủ trang cần khắc phục. Nếu giờ nó lỗi với ERR_CONTENT_LENGTH_MISMATCH hoặc ERR_INCOMPLETE_CHUNKED_ENCODING, máy chủ đang cắt cụt phản hồi bất kể giao thức nào. Hãy đóng cửa sổ đó khi xong việc; Chrome thông thường của bạn không bị ảnh hưởng.
Dành cho chủ website: khắc phục lỗi giao thức HTTP/2
Nếu khách truy cập trên nhiều mạng và trình duyệt khác nhau đều báo lỗi, vấn đề nằm trong hệ thống của bạn. Ba bước kiểm tra sau tìm ra gần như tất cả nguyên nhân.
1. Tái hiện lỗi bằng 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/nullNếu HTTP/1.1 hoạt động còn HTTP/2 thất bại, HTTP/2 có liên quan. "Reset by server" cho thấy máy chủ hoặc một proxy đã bỏ cuộc giữa chừng phản hồi. curl không kiểm tra chính xác những gì Chrome kiểm tra (nó từ chối Content-Length không khớp và các header kết nối mà Chrome cho qua), nên hãy coi đây là gợi ý mạnh chứ không phải bằng chứng. Công cụ Kiểm tra HTTP Header liệt kê các header mà ứng dụng của bạn đặt, khi nhìn từ bên ngoài mạng của bạn.
2. Kiểm tra phản hồi bị cắt giữa chừng
Nguyên nhân phổ biến nhất ở phía máy chủ là phản hồi đã bắt đầu (trạng thái 200, header đã gửi) rồi không thể hoàn tất. nginx lưu tạm các phản hồi lớn từ ứng dụng của bạn vào tệp tạm, và nếu ổ đĩa đầy hoặc nginx không ghi được vào thư mục tạm, nó sẽ reset luồng và trình duyệt báo lỗi giao thức. Hãy kiểm tra:
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 userHãy kiểm tra cả bản thân ứng dụng: một tiến trình PHP hoặc Node bị crash, hết thời gian chờ hoặc chạm giới hạn bộ nhớ trong khi truyền một trang hay tệp tải xuống lớn cũng tạo ra kết quả tương tự. Log của ứng dụng quanh thời điểm xảy ra lỗi thường cho thấy điều đó.
3. Sửa Content-Length và các header bị cấm
- Content-Length: hãy để máy chủ tự tính. Đừng tự đặt giá trị này trong mã ứng dụng nếu một plugin, middleware hoặc máy chủ web cũng nén hoặc sửa đổi đầu ra, vì khi đó độ dài khai báo sẽ không còn khớp với số byte được gửi. Độ dài được đặt trong mã PHP trong khi một plugin hoặc thiết lập PHP cũng nén đầu ra là một cách điều này xảy ra trên các trang WordPress.
- Transfer-Encoding: đừng bao giờ gửi nó trong phản hồi HTTP/2; Chrome reset luồng khi thấy header này. RFC 9113 cũng cấm
Connection,Keep-Alive,Proxy-ConnectionvàUpgrade. Chrome bỏ qua chúng, nhưng curl và các client nghiêm ngặt khác từ chối, và nginx tự loại bỏ phần lớn chúng khỏi các phản hồi được proxy. - Giá trị header: đảm bảo không header nào chứa ký tự xuống dòng hoặc ký tự điều khiển. Điều này thường đến từ dữ liệu người dùng nhập được đặt vào header, chẳng hạn tên tệp trong
Content-Disposition. - CDN phía trước: nếu bạn dùng Cloudflare hoặc CDN khác, hãy kiểm tra trực tiếp máy chủ gốc (bằng curl
--resolvehoặc một mục trong tệp hosts) để biết lỗi đến từ máy chủ gốc hay từ CDN.
ERR_HTTP2_PROTOCOL_ERROR khác gì các lỗi tương tự
| Lỗi | Mã | Điều đã xảy ra |
|---|---|---|
| ERR_HTTP2_PROTOCOL_ERROR | -337 | Một phản hồi HTTP/2 vi phạm quy tắc giao thức |
| ERR_QUIC_PROTOCOL_ERROR | -356 | Cùng loại lỗi nhưng qua HTTP/3 (QUIC) |
| ERR_SSL_PROTOCOL_ERROR | -107 | Quá trình bắt tay HTTPS (TLS) thất bại trước khi HTTP/2 bắt đầu |
| ERR_CONNECTION_CLOSED | -100 | Kết nối bị đóng trước khi trang được gửi đến |
| ERR_EMPTY_RESPONSE | -324 | Máy chủ hoàn toàn không gửi gì |
Hướng dẫn chi tiết: ERR_QUIC_PROTOCOL_ERROR, ERR_SSL_PROTOCOL_ERROR, ERR_CONNECTION_CLOSED và ERR_EMPTY_RESPONSE. Để kiểm tra chứng chỉ và thiết lập HTTPS của một trang web từ bên ngoài, hãy dùng Kiểm tra chứng chỉ SSL.
Xem các header mà trang của bạn thực sự gửi
Công cụ Kiểm tra HTTP Header của DNS Robot tải bất kỳ URL nào từ máy chủ của chúng tôi qua HTTP/1.1 và liệt kê mã trạng thái cùng mọi header phản hồi mà ứng dụng của bạn đặt (Content-Length, Content-Encoding, Content-Disposition), để bạn so sánh với kết quả của curl --http2.
Nguồn
- net_error_list.h (HTTP2_PROTOCOL_ERROR -337), Chromium
- RFC 9113: HTTP/2, malformed messages, IETF
- HTTP/2: ERR_HTTP2_PROTOCOL_ERROR, Cloudflare


