Перейти до основного вмісту

Посібники / Виправити: посібники для помилок, з якими стикаються насправді

ERR_QUIC_PROTOCOL_ERROR: what it means and how to fix it

ERR_QUIC_PROTOCOL_ERROR means Chrome lost a QUIC (HTTP/3) connection after it had been set up, usually because something on the path mishandles UDP traffic on port 443 or because the HTTP/3 stack of the server misbehaved. Turning QUIC off in Chrome shows quickly whether it is the cause.

What ERR_QUIC_PROTOCOL_ERROR means

Chromium defines QUIC_PROTOCOL_ERROR (-356) as "There is a QUIC protocol error." QUIC is the transport protocol of HTTP/3: RFC 9000 defines QUIC, and RFC 9114 defines HTTP/3 on top of it. QUIC runs over UDP instead of TCP, so it uses a different network path than HTTP/1.1 and HTTP/2. A server announces HTTP/3 with an Alt-Svc response header such as h3=":443", and a browser may then open a QUIC connection to it on the next visit. RFC 9114 adds that blocked UDP can make a QUIC connection fail, and that clients SHOULD then use HTTP over TCP.

The Chromium source shows what the code means in practice. If the QUIC handshake never finishes, Chrome reports a different error, ERR_QUIC_HANDSHAKE_FAILED (-358), and retries the request. ERR_QUIC_PROTOCOL_ERROR is the general code for a connection or stream that was set up and then ended with an error, and for a response that broke the rules of HTTP/3, such as invalid headers. So at least some UDP traffic did get through before the error.

Chrome also retries on its own. When the error happens before the response headers arrive, Chrome sends the request again without HTTP/3, over TCP, and if that works it marks the HTTP/3 service of the site as broken for a delay that grows with repeated failures. The error page therefore tends to appear when a retry is not possible: the response had already started, or the retry failed as well. That is why DevTools often shows a request like this, where the status line arrived and the body did not:

GET https://example.com/downloads/report.zip net::ERR_QUIC_PROTOCOL_ERROR 200 (OK)

How the error appears

Chrome has no special text for this code, so it shows the general "This site can't be reached" page with ERR_QUIC_PROTOCOL_ERROR at the bottom. Edge, Brave, Opera and other Chromium browsers show the same code. Sometimes there is no error page at all: a page loads, but one image, script or download fails, and the error is only visible in the DevTools console.

To see which protocol a site uses, open DevTools, go to the Network panel, right-click the column headers, and enable "Protocol". The value h3 means HTTP/3, h2 means HTTP/2. From the command line, look for the Alt-Svc header, and test HTTP/3 directly if your curl supports it (curl -V lists HTTP3 in its features):

curl -sI https://example.com/ | grep -i alt-svc
alt-svc: h3=":443"; ma=86400

curl --http3-only -sS -o /dev/null -w 'h3: %{http_version} %{http_code}\n' https://example.com/
h3: 3 200
curl --http2 -sS -o /dev/null -w 'h2: %{http_version} %{http_code}\n' https://example.com/
h2: 2 200

A server without a working HTTP/3 listener fails the second command, for example with curl: (7) Failed to connect to example.com:443 after 246 ms: Could not connect to server. If a firewall drops the packets without any answer, the command waits and ends with curl: (28) Connection timed out. A server that passes both commands can still fail in the browser when the problem sits on the network of the visitor.

ERR_QUIC_PROTOCOL_ERROR vs similar errors

The first two rows are close relatives. The others come from the TCP side of the same page load. The numbers are Chromium's internal error codes.

ErrorWhat happened at the network or protocol levelWhere to look first
ERR_QUIC_PROTOCOL_ERROR (-356)A QUIC connection was set up, then a stream or the whole connection ended with an error, or the response broke HTTP/3 rules.The UDP path (firewall, NAT, MTU), the HTTP/3 stack of the server, UDP load balancers.
ERR_QUIC_HANDSHAKE_FAILED (-358)The QUIC handshake did not complete. Chrome retries the request.Whether UDP 443 reaches the server at all.
ERR_HTTP2_PROTOCOL_ERRORTLS worked, but a frame or stream broke the rules of HTTP/2 over TCP.Proxy and CDN HTTP/2 settings, header sizes.
ERR_SSL_PROTOCOL_ERROR (-107)The TLS handshake over TCP received data it could not use.The TLS configuration, and the protocol that the port really speaks.
ERR_CONNECTION_RESET (-101)An open TCP connection was ended by an RST.Proxy, WAF and application logs; antivirus, VPN or filtering on the client side.
ERR_CONNECTION_TIMED_OUT (-118)The TCP SYN went out and nothing came back until the client gave up.Firewalls that drop packets, and whether the host is up.

What causes ERR_QUIC_PROTOCOL_ERROR

  • UDP 443 is filtered or limited. A firewall, router or security product lets the first packets through and drops later ones, or limits the rate of UDP. Some company firewalls treat QUIC as unknown traffic.
  • The path drops large packets. RFC 9000 requires UDP datagrams of at least 1200 bytes for the first QUIC packets. A VPN, tunnel or PPPoE link with a small MTU, or a device that drops fragments, breaks this.
  • NAT and idle timeouts. A NAT device forgets a UDP mapping after a short idle time, and the packets of the server then go nowhere.
  • A VPN, proxy or antivirus that handles UDP badly. Software on the device can block, inspect or rewrite UDP traffic.
  • The server loses state. After a restart or a crash, the server has no record of old connections. RFC 9000 describes the stateless reset for this case, and the client sees the connection end.
  • A load balancer that is not QUIC-aware. Packets of one connection must reach the same backend. Balancing by source address and port alone can break when a NAT changes the port of the client.
  • HTTP/3 is advertised but not reachable. The server sends Alt-Svc, but UDP 443 is closed in a firewall, a cloud security group, or a Docker port mapping.
  • Bugs in an HTTP/3 implementation. A server or CDN edge that sends invalid headers or frames, or an old browser, can end a connection with a protocol error.
  • Chrome flags and extensions. Experimental flags and extensions that change network behavior can interfere.

Server-side causes and configuration

If you run the site, check that HTTP/3 works end to end, from the internet to the process that answers, or turn it off cleanly.

Find the QUIC error in a Chrome log

Open chrome://net-export, click "Start Logging to Disk", reproduce the error, click "Stop Logging", and open the file in the NetLog viewer that the page links to. Find the QUIC_SESSION_CLOSED event. Its quic_error field names the reason, and from_peer says whether the server ended the connection. These values from the QUIC library of Chromium are common:

quic_errorMeaning in the libraryWhere to look first
QUIC_TOO_MANY_RTOSQUIC timed out after too many retransmission timeouts: packets were sent and never acknowledged.Packet loss on the UDP path: firewall, NAT, MTU, an overloaded server.
QUIC_NETWORK_IDLE_TIMEOUTThe connection timed out due to no network activity.NAT mappings that expire, or a path that drops packets without any answer.
QUIC_PUBLIC_RESETA reset for this connection was received.A server restart, or a load balancer that sent packets to another backend.
QUIC_PACKET_WRITE_ERRORAn error occurred while writing to the socket.The network stack on the device: VPN, firewall driver, adapter.

Open UDP 443 in every layer

TCP 443 and UDP 443 are different ports for firewalls. Check each layer that has its own rules:

# Is something listening on UDP 443?
sudo ss -lunp | grep ':443'

# ufw
sudo ufw allow 443/udp

# iptables
sudo iptables -A INPUT -p udp --dport 443 -j ACCEPT

# Docker: publish the UDP port next to the TCP port
docker run -d -p 443:443/tcp -p 443:443/udp my-web-image

In cloud security groups and network ACLs, add an inbound rule for UDP 443. In Kubernetes, a Service needs its own port entry for UDP:

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - name: https
      protocol: TCP
      port: 443
      targetPort: 8443
    - name: http3
      protocol: UDP
      port: 443
      targetPort: 8443

nginx

The nginx documentation lists HTTP/3 support since version 1.25.0, with the module marked experimental. It recommends the same port for HTTP/3 and HTTPS. The listener needs the quic parameter, and the response needs the Alt-Svc header:

server {
    listen 443 quic reuseport;   # HTTP/3 over UDP
    listen 443 ssl;              # HTTPS over TCP
    server_name example.com;
    ssl_certificate     /etc/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.com/privkey.pem;
    add_header Alt-Svc 'h3=":443"; ma=86400' always;
}

The ma value is how long, in seconds, clients may remember the HTTP/3 service (86400 is 24 hours). To switch HTTP/3 off, remove the quic listener and the Alt-Svc header. Clients that remembered the old header keep trying until ma runs out. Send add_header Alt-Svc 'clear' always; for a while instead: RFC 7838 defines clear to invalidate all alternative services of the origin. The nginx debug log marks all QUIC messages with the prefix "quic", which makes them easy to filter.

Caddy

Caddy serves HTTP/3 by default. Its documentation lists h1 h2 h3 as the default for the protocols option. To turn HTTP/3 off, set the list without h3:

{
    servers {
        protocols h1 h2
    }
}

CDNs and load balancers

Most CDNs have a switch for HTTP/3 in their network settings. If the errors started after a CDN or load balancer change, switch HTTP/3 off there first and see whether they stop. For your own UDP load balancers, make sure that packets of one QUIC connection reach the same backend even when the source port of the client changes.

How it looks from the outside

  • Works over HTTP/2 and fails over HTTP/3, from every location: the HTTP/3 stack of the server or CDN is at fault. Turn HTTP/3 off at that layer while you investigate.
  • Fails only from some networks: a firewall or provider on those networks mishandles UDP 443. The server is fine, and Chrome falls back to TCP in most cases.
  • Fails only for you, while other browsers or devices work: the cause is on your device or router, such as security software, a VPN, a Chrome flag or an extension.
  • Large files and long responses fail, small pages load: the failure happens after the headers arrived, so Chrome cannot retry. Look for MTU problems, UDP rate limits and idle timeouts.
  • Errors appear after deploys or restarts: the server lost connection state, or the load balancer moved connections.

UDP 443 is a separate network path from TCP 443, so a page that loads over TCP says nothing about HTTP/3. Test HTTP/3 directly with the curl commands above, and compare with the HTTP checker, which checks a host's HTTP status, response time and server availability from locations worldwide.

How to fix ERR_QUIC_PROTOCOL_ERROR

If you are a visitor

  1. Reload the page. Chrome often retries over TCP by itself, and it remembers that HTTP/3 failed for that site.
  2. Try another network and turn off the VPN. If the site works on mobile data, the first network or the VPN blocks or mangles UDP.
  3. Update Chrome in chrome://settings/help and restart it.
  4. Turn QUIC off in Chrome. Open chrome://flags/#enable-quic, set "Experimental QUIC protocol" to "Disabled", and click "Relaunch". The name and the position of this flag can change between Chrome versions, so search for "QUIC" in chrome://flags if you do not find it. Edge and other Chromium browsers have their own flags page, for example edge://flags. Sites keep working over TCP.
  5. Start Chrome without QUIC if you prefer a command-line switch. On Windows, run chrome.exe --disable-quic from the installation folder. On macOS, run open -a "Google Chrome" --args --disable-quic. On Linux, run google-chrome --disable-quic.
  6. Disable extensions or use a private window. If the error disappears, turn the extensions back on one at a time.
  7. Check security software and the router. Some products block or inspect QUIC. On a company computer, ask the IT team to allow UDP 443 or to set the Chrome policy QuicAllowed to false, which disallows QUIC.

If you run the site

  1. Check what you advertise: curl -sI https://example.com/ | grep -i alt-svc.
  2. Compare HTTP/3 and HTTP/2 with the two curl commands above, from your own network and from a server in another network.
  3. Open UDP 443 in the host firewall, the cloud security group, the container mapping and the load balancer, and check the listener with ss -lunp.
  4. Read the server logs for QUIC errors at the time of the failure, and update the web server and its TLS library to versions that the vendor lists for HTTP/3.
  5. If you cannot fix it quickly, turn HTTP/3 off at the CDN or the web server, and send Alt-Svc: clear for a while. Visitors then use HTTP/2 over TCP.
  6. Verify with the Protocol column in DevTools after each change.

Monitoring a site that offers HTTP/3

An HTTP/3 problem often affects some networks and regions and not others, so the pattern matters more than a single result. HostTracker has monitored websites since 2004 and checks them from 300+ checkpoints in 158 cities, with alerts by email, SMS, voice call, Slack, Telegram and more. After every change to firewalls, load balancers or CDN settings, also test UDP 443 directly with curl, because it is a separate path.

Frequently asked questions

What is the difference between QUIC and HTTP/3?

QUIC is a transport protocol that runs over UDP and is defined in RFC 9000. HTTP/3 is the version of HTTP that runs on QUIC, defined in RFC 9114. Both are encrypted: HTTP/3 uses TLS 1.3 inside QUIC, and browsers use HTTP/2 only over TLS on TCP.

Is it safe to disable QUIC in Chrome?

Yes. Websites keep working over HTTP/2 or HTTP/1.1 on TCP, and that traffic is encrypted with TLS as well. You only lose the features of HTTP/3.

Does ERR_QUIC_PROTOCOL_ERROR mean the website is down?

No. The same site normally still works over TCP. The error says that the HTTP/3 connection failed on its way, and the cause can be your network, the server or anything between them.

Why does it only happen with large files?

Chrome can retry a request over TCP only before the response headers have arrived. A failure in the middle of a large body leaves nothing to retry, and the error page or the console message appears. Packet loss, MTU limits and idle timeouts hit long transfers more often.

Why do I see it in Chrome and Edge but not in Firefox?

Chrome and Edge share the Chromium network stack and its error codes. Firefox has its own HTTP/3 implementation and its own error messages, so the same network problem looks different there.

Do I need HTTP/3 on my server?

No. HTTP/3 is optional, and HTTP/2 over TCP works for every browser. If you cannot keep UDP 443 reliable end to end, turning HTTP/3 off is a valid choice.

Sources and further reading

  • Chromium net error list: the definitions of QUIC_PROTOCOL_ERROR (-356), QUIC_HANDSHAKE_FAILED (-358) and the other codes in the table above.
  • RFC 9114, HTTP/3: section 3.1 on discovering an HTTP/3 endpoint and falling back to TCP, and section 3.1.1 on the Alt-Svc header.
  • RFC 9000, QUIC: section 14.1 on the 1200-byte datagram size, and section 10.3 on stateless reset.
  • nginx: ngx_http_v3_module: the quic listener, the Alt-Svc example and the HTTP/3 directives.

Перевірити зараз

Запустіть безкоштовну перевірку власного сайту - обліковий запис не потрібен.

HTTP check

Стежити за цим постійно

Отримуйте сповіщення в момент збою: HostTracker перевіряє з понад 300 локацій і повідомляє вас електронною поштою, SMS, у Slack, Telegram та інших каналах.

Можливості HostTracker

Ще в цьому розділі: Виправити: посібники для помилок, з якими стикаються насправді