What's the net::ERR_HTTP2_PROTOCOL_ERROR about

2020-02-10 02:45发布

问题:

I'm currently working on a website, which triggers a net::ERR_HTTP2_PROTOCOL_ERROR 200 error on Google Chrome. I'm not sure exactly what can provoke this error, I just noticed it pops out only when accessing the website in HTTPS. I can't be 100% sure it is related, but it looks like it prevents javascript to be executed properly.

For instance, the following scenario happens :

  1. I'm accessing the website in HTTPS

  2. My Twitter feed integrated via https://publish.twitter.com isn't loaded at all

  3. I can notice in the console the ERR_HTTP2_PROTOCOL_ERROR

  4. If I remove the code to load the Twitter feed, the error remains

  5. If I access the website in HTTP, the Twitter feed appears and the error disappears

Google Chrome is the only web browser triggering the error: it works well on both Edge and Firefox. (NB: I tried with Safari, and I have a similar kcferrordomaincfnetwork 303 error)

I was wondering if it could be related to the header returned by the server since there is this '200' mention in the error, and a 404 / 500 page isn't triggering anything.

Thing is the error isn't documented at all. Google search gives me very few results. Moreover, I noticed it appears on very recent Google Chrome releases; the error doesn't pop on v.64.X, but it does on v.75+ (regardless of the OS; I'm working on Mac tho).

Any clue at this point to investigate would be gladly appreciated !

Thanks in advance.

Tristan


Edit 1 : Might be related to Website OK on Firefox but not on Safari (kCFErrorDomainCFNetwork error 303) neither Chrome (net::ERR_SPDY_PROTOCOL_ERROR)


Edit 2 : Findings from further investigations are the following :

  • error doesn't pop on the exact same page if server returns 404 instead of 2XX
  • error doesn't pop on local with a HTTPS certificate
  • error pops on a different server (both are OVH's), which uses a different certificate
  • error pops no matter what PHP version is used, from 5.6 to 7.3 (framework used : Cakephp 2.10)

Edit 3 : As requested, below is the returned header for the failing ressource, which is the whole web page. Even if the error is triggering on each page having a HTTP header 200, those pages are always loading on client's browser, but sometimes an element is missing (in my exemple, the external Twitter feed). Every other asset on the Network tab has a success return, except the whole document itself.

Google Chrome header (with error) :

Firefox header (without error) :

A curl --head --http2 request in console returns the following success :

HTTP/2 200 
date: Fri, 04 Oct 2019 08:04:51 GMT
content-type: text/html; charset=UTF-8
content-length: 127089
set-cookie: SERVERID31396=2341116; path=/; max-age=900
server: Apache
x-powered-by: PHP/7.2
set-cookie: xxxxx=0919c5563fc87d601ab99e2f85d4217d; expires=Fri, 04-Oct-2019 12:04:51 GMT; Max-Age=14400; path=/; secure; HttpOnly
vary: Accept-Encoding

Edit 4 : Trying to go deeper with the chrome://net-export/ and https://netlog-viewer.appspot.com tools is telling me the request ends with a RST_STREAM :

t=123354 [st=5170]    HTTP2_SESSION_RECV_RST_STREAM
                      --> error_code = "2 (INTERNAL_ERROR)"
                      --> stream_id = 1

For what I read in this other post, "In HTTP/2, if the client wants to abort the request, it sends a RST_STREAM. When the server receives a RST_STREAM, it will stop sending DATA frames to the client, thereby stopping the response (or the download). The connection is still usable for other requests, and requests/responses that were concurrent with the one that has been aborted may continue to progress. [...] It is possible that by the time the RST_STREAM travels from the client to the server, the whole content of the request is in transit and will arrive to the client, which will discard it. However, for large response contents, sending a RST_STREAM may have a good chance to arrive to the server before the whole response content is sent, and therefore will save bandwidth."

The described behavior is the same as the one I can observe. But that would mean the browser is the culprit, and then I wouldn't understand why it happens on two identical pages with one having a 200 header and the other a 404 (same goes if I disable JS).

回答1:

for several weeks I was also annoyed by this "bug" "net :: ERR_HTTP2_PROTOCOL_ERROR 200", it occurred on images generated by PHP. Finally, it is at the level of the headers and in particular on "header ('Content-Length:'. Filesize($cache_file));" which obviously did not return the exact size ... I deleted this header and everything works perfectly now. Visibly so Chrome checks the accuracy of the data transmitted via the headers, if it does not correspond = "failed"

Yours truly

EDIT: 14/11/2019 at 15:15 I found the reason for the miscalculation of content-lenght via filesize: the GZIP compression is active on the PHP files, so just exclude the file in question via a "SetEnvIfNoCase Request_URI ^ / thumb.php no-gzip -vary "in the .htaccess. It also works and we keep the header Content-lenght.



回答2:

ALL RIGHT

I didn't figure out what exactly was happening, but I found a solution. It looks like the CDN feature of OVH was the culprit. I had it installed on my host service, but disabled for my domain (because I don't feel like I need it anyway). Somehow, when enabling it, everything works. I guess it forces Apache to use the HTTP2 protocol ; what I don't understand yet is that there indeed was a HTTP2 mention in each of my headers, which I presume means the server was answering using the right protocol.

Anyway, solution for my very particular case is to enable this CDN option on all concerned domains. If anyone understands better what could have happened here, feel free to share explanations.

Thanks a lot to anyone that helped !



回答3:

I encountered this because the http2 server closed the connection when sending a big response to the Chrome.

Why? Because it is just a setting of the http2 server, named WriteTimeout.



回答4:

I experienced a similar problem, I was getting ERR_HTTP2_PROTOCOL_ERROR on one of the HTTP GET requests.

I noticed that the Chrome update was pending, so I updated the Chrome browser to the latest version and the error was gone next time when I relaunched the browser.



回答5:

I had this problem when having a Nginx server that exposing the node-js application to the external world. The Nginx made the file (css, js, ...) compressed with gzip and with Chrome it looked like the same.

The problem solved when we found that the node-js server is also compressed the content with gzip. In someway, this double compressing leading to this problem. Canceling node-js compression solved the issue.



回答6:

In my case it was - no disk space left on the web server.



回答7:

I got the same issue (asp, c# - HttpPostedFileBase) when posting a file that was larger than 1MB (even though application doesn't have any limitation for file size), for me the simplification of model class helped. If you got this issue, try to remove some parts of the model, and see if it will help in any way. Sounds strange, but worked for me.



回答8:

I have been experiencing this problem for the last week now as I've been trying to send DELETE requests to my PHP server through AJAX. I recently upgraded my hosting plan where I now have an SSL Certificate on my host which stores the PHP and JS files. Since adding an SSL Certificate I no longer experience this issue. Hoping this helps with this strange error.



回答9:

This happened to me when I registered a new domain name, e.g., "new" for example.com (new.example.com). The name could not be resolved temporarily in my location for a couple of hours, while it could be resolved abroad. So I used a proxy to test the website where I saw net::ERR_HTTP2_PROTOCOL_ERROR in chrome console for some AJAX posts. Hours later, when the name could be resloved locally, those error just dissappeared.

I think the reason for that error is those AJAX requests were not redirected by my proxy, it just visit a website which had not been resolved by my local DNS resolver.