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

Trang lỗi Chrome hiển thị ERR_HTTP2_PROTOCOL_ERROR bên cạnh các bước kiểm tra giúp khắc phục lỗi giao thức HTTP/2
Trang lỗi Chrome hiển thị ERR_HTTP2_PROTOCOL_ERROR bên cạnh các bước kiểm tra giúp khắc phục lỗi giao thức HTTP/2
Bắt đầu đọc
  1. ERR_HTTP2_PROTOCOL_ERROR là gì?
  2. Những gì HTTP/2 coi là sai định dạng
  3. Nguyên nhân gây ra lỗi ERR_HTTP2_PROTOCOL_ERROR
  4. Cách 1: tải lại cứng và thử chế độ ẩn danh
  5. Cách 2: xóa cookie và tệp đã lưu của trang web đó
  6. 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
  7. Cách 4: cập nhật Chrome và kiểm tra trên trình duyệt khác
  8. Cách 5: kiểm tra trang khi không dùng HTTP/2
  9. Dành cho chủ website: khắc phục lỗi giao thức HTTP/2
  10. 1. Tái hiện lỗi bằng curl
  11. 2. Kiểm tra phản hồi bị cắt giữa chừng
  12. 3. Sửa Content-Length và các header bị cấm
  13. ERR_HTTP2_PROTOCOL_ERROR khác gì các lỗi tương tự
  14. 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ânMá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àngMá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ốiTransfer-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ườngTê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ở:

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

Nế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

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

Nế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:

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

Hã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-Connection và 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 --resolve hoặ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ỗiMãĐiều đã xảy ra
ERR_HTTP2_PROTOCOL_ERROR-337Một phản hồi HTTP/2 vi phạm quy tắc giao thức
ERR_QUIC_PROTOCOL_ERROR-356Cùng loại lỗi nhưng qua HTTP/3 (QUIC)
ERR_SSL_PROTOCOL_ERROR-107Quá trình bắt tay HTTPS (TLS) thất bại trước khi HTTP/2 bắt đầu
ERR_CONNECTION_CLOSED-100Kết nối bị đóng trước khi trang được gửi đến
ERR_EMPTY_RESPONSE-324Má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

  1. net_error_list.h (HTTP2_PROTOCOL_ERROR -337), Chromium
  2. RFC 9113: HTTP/2, malformed messages, IETF
  3. HTTP/2: ERR_HTTP2_PROTOCOL_ERROR, Cloudflare

Câu hỏi thường gặp

Lỗi ERR_HTTP2_PROTOCOL_ERROR có nghĩa là gì?

Nó nghĩa là luồng HTTP/2 chứa trang đã thất bại. Thường thì máy chủ, proxy hoặc CDN đã reset luồng trước khi phản hồi kết thúc, và Chrome báo đó là lỗi giao thức; đôi khi Chrome từ chối các header mà HTTP/2 cấm, chẳng hạn Transfer-Encoding. Trong Chromium, đây là mã lỗi mạng -337.

ERR_HTTP2_PROTOCOL_ERROR là lỗi của tôi hay của trang web?

Thường là của trang web. Nhưng tính năng quét HTTPS của phần mềm diệt virus, tiện ích mở rộng của trình duyệt hoặc cookie quá lớn cũng có thể gây ra lỗi, vì vậy hãy thử tải lại cứng, mở cửa sổ Ẩn danh và tạm dừng quét HTTPS trước. Nếu lỗi xảy ra trên mọi trình duyệt và mọi mạng, chỉ chủ trang web mới khắc phục được.

net::ERR_HTTP2_PROTOCOL_ERROR 200 có nghĩa là gì?

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: máy chủ, proxy hoặc CDN đã reset luồng giữa chừng. Nguyên nhân thường gặp là proxy hết dung lượng ổ đĩa hoặc không ghi được tệp tạm, ứng dụng bị crash giữa phản hồi, hoặc Content-Length không khớp với phần thân.

Cách sửa lỗi ERR_HTTP2_PROTOCOL_ERROR trên Chrome?

Tải lại cứng bằng Ctrl + Shift + R, thử chế độ Ẩn danh, xóa cookie và tệp đã lưu của trang, tạm dừng quét HTTPS của phần mềm diệt virus, tắt tiện ích mở rộng và cập nhật Chrome. Để kiểm tra HTTP/2 có liên quan hay không, hãy khởi chạy một Chrome riêng với --user-data-dir, --disable-http2 và --disable-quic rồi xem trang có tải được không.

Có thể tắt HTTP/2 trong Chrome không?

Không thể tắt từ trang cài đặt. Để kiểm tra, hãy khởi chạy một Chrome riêng với --disable-http2 và --disable-quic (cùng --user-data-dir, nếu không Chrome đang chạy sẽ bỏ qua các cờ). Chúng chỉ áp dụng cho lần khởi chạy đó. Đây là công cụ chẩn đoán, không phải giải pháp lâu dài, vì HTTP/2 giúp trang web nhanh hơn.

Tại sao lỗi ERR_HTTP2_PROTOCOL_ERROR xảy ra trên trang nginx của tôi?

Kiểm tra xem ổ đĩa có bị đầy hoặc nginx có không ghi được vào thư mục tạm của proxy hay FastCGI không (tìm "No space left on device" hoặc "Permission denied" trong log lỗi), ứng dụng có bị crash giữa chừng không, và ứng dụng có gửi header Transfer-Encoding hoặc Content-Length sai không. Tái hiện lỗi bằng curl --http2 -v.

Cloudflare có thể gây ra ERR_HTTP2_PROTOCOL_ERROR không?

Thường là máy chủ gốc có lỗi. Tài liệu của Cloudflare nêu header sai định dạng từ máy chủ gốc và sự cố nén (phần thân gzip có Content-Length chưa được cập nhật, hoặc gzip bị hỏng) là các nguyên nhân thường gặp, và chúng có thể chỉ lộ ra khi lưu lượng đi qua Cloudflare. Hãy kiểm tra trực tiếp máy chủ gốc, bỏ qua Cloudflare.

ERR_HTTP2_PROTOCOL_ERROR và ERR_QUIC_PROTOCOL_ERROR khác nhau thế nào?

Chúng là cùng một loại lỗi trên các giao thức khác nhau. ERR_HTTP2_PROTOCOL_ERROR xảy ra qua HTTP/2 (trên TCP), còn ERR_QUIC_PROTOCOL_ERROR qua HTTP/3 (trên QUIC). Tường lửa và phần mềm diệt virus can thiệp vào QUIC là một nguyên nhân phổ biến khác của lỗi thứ hai.

Xóa bộ nhớ đệm có sửa được ERR_HTTP2_PROTOCOL_ERROR không?

Đôi khi. Xóa cookie và tệp đã lưu của trang sẽ thay đổi yêu cầu mà Chrome gửi đi, và có thể né được lỗi của máy chủ, nên đáng để thử. Nếu máy chủ vẫn tiếp tục reset luồng hoặc gửi header sai, lỗi sẽ quay lại cho đến khi trang web được sửa.

Về tác giả

Shaik Vahid

Nhà sáng lập DNS Robot. Vahid đã làm nhiều năm trong bộ phận hỗ trợ hosting, xử lý tên miền, bản ghi DNS, chứng chỉ SSL và việc gửi email cho khách hàng. Anh xây dựng các công cụ của DNS Robot và viết những hướng dẫn này từ các lỗi mà mọi người thực sự gặp.

Kiểm tra HTTP Header

Phân tích header phản hồi HTTP và chấm điểm header bảo mật