ERR_QUIC_PROTOCOL_ERROR: o que significa e como corrigir
ERR_QUIC_PROTOCOL_ERROR significa que o Chrome perdeu uma conexão QUIC (HTTP/3) depois de ela já ter sido estabelecida, geralmente porque algo no caminho trata mal o tráfego UDP na porta 443 ou porque a pilha HTTP/3 do servidor se comportou mal. Desativar o QUIC no Chrome mostra rapidamente se ele é a causa.
O que significa ERR_QUIC_PROTOCOL_ERROR
O Chromium define QUIC_PROTOCOL_ERROR (-356) como “There is a QUIC protocol error.” (há um erro de protocolo QUIC). O QUIC é o protocolo de transporte do HTTP/3: a RFC 9000 define o QUIC, e a RFC 9114 define o HTTP/3 em cima dele. O QUIC roda sobre UDP em vez de TCP, então usa um caminho de rede diferente do HTTP/1.1 e do HTTP/2. Um servidor anuncia o HTTP/3 com um cabeçalho de resposta Alt-Svc, como h3=":443", e o navegador pode então abrir uma conexão QUIC com ele na próxima visita. A RFC 9114 acrescenta que um UDP bloqueado pode fazer uma conexão QUIC falhar, e que os clientes DEVEM então usar HTTP sobre TCP.
O código-fonte do Chromium mostra o que o código significa na prática. Se o handshake QUIC nunca termina, o Chrome reporta outro erro, ERR_QUIC_HANDSHAKE_FAILED (-358), e tenta a requisição de novo. O ERR_QUIC_PROTOCOL_ERROR é o código geral para uma conexão ou um stream que foi estabelecido e depois terminou com erro, e para uma resposta que quebrou as regras do HTTP/3, como cabeçalhos inválidos. Ou seja, pelo menos parte do tráfego UDP chegou a passar antes do erro.
O Chrome também tenta de novo por conta própria. Quando o erro acontece antes de os cabeçalhos da resposta chegarem, o Chrome envia a requisição outra vez sem HTTP/3, por TCP, e, se isso funciona, marca o serviço HTTP/3 do site como quebrado por um intervalo que cresce a cada falha repetida. Por isso a página de erro tende a aparecer quando uma nova tentativa não é possível: a resposta já tinha começado, ou a nova tentativa também falhou. É por isso que o DevTools costuma mostrar uma requisição assim, em que a linha de status chegou e o corpo não:
GET https://example.com/downloads/report.zip net::ERR_QUIC_PROTOCOL_ERROR 200 (OK)
Como o erro aparece
O Chrome não tem um texto especial para esse código, então mostra a página geral “This site can't be reached” com ERR_QUIC_PROTOCOL_ERROR no rodapé. Edge, Brave, Opera e outros navegadores baseados em Chromium mostram o mesmo código. Às vezes não há página de erro nenhuma: a página carrega, mas uma imagem, um script ou um download falha, e o erro só é visível no console do DevTools.
Para ver qual protocolo um site usa, abra o DevTools, vá ao painel Network, clique com o botão direito nos cabeçalhos das colunas e ative “Protocol”. O valor h3 significa HTTP/3, e h2 significa HTTP/2. Pela linha de comando, procure o cabeçalho Alt-Svc e teste o HTTP/3 diretamente, se o seu curl suportar (curl -V lista HTTP3 entre os recursos):
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
Um servidor sem um listener HTTP/3 funcionando falha no segundo comando, por exemplo com curl: (7) Failed to connect to example.com:443 after 246 ms: Could not connect to server. Se um firewall descarta os pacotes sem nenhuma resposta, o comando espera e termina com curl: (28) Connection timed out. Um servidor que passa nos dois comandos ainda pode falhar no navegador quando o problema está na rede do visitante.
ERR_QUIC_PROTOCOL_ERROR e erros parecidos
As duas primeiras linhas são parentes próximos. As outras vêm do lado TCP do mesmo carregamento de página. Os números são os códigos de erro internos do Chromium.
| Erro | O que aconteceu no nível da rede ou do protocolo | Onde olhar primeiro |
|---|---|---|
| ERR_QUIC_PROTOCOL_ERROR (-356) | Uma conexão QUIC foi estabelecida e depois um stream ou a conexão inteira terminou com erro, ou a resposta quebrou as regras do HTTP/3. | O caminho UDP (firewall, NAT, MTU), a pilha HTTP/3 do servidor, balanceadores de carga UDP. |
| ERR_QUIC_HANDSHAKE_FAILED (-358) | O handshake QUIC não foi concluído. O Chrome tenta a requisição de novo. | Se a UDP 443 chega ao servidor. |
| ERR_HTTP2_PROTOCOL_ERROR | O TLS funcionou, mas um frame ou stream quebrou as regras do HTTP/2 sobre TCP. | As configurações de HTTP/2 do proxy e do CDN, tamanhos de cabeçalho. |
| ERR_SSL_PROTOCOL_ERROR (-107) | O handshake TLS sobre TCP recebeu dados que não pôde usar. | A configuração TLS e o protocolo que a porta realmente fala. |
| ERR_CONNECTION_RESET (-101) | Uma conexão TCP aberta foi encerrada por um RST. | Os logs do proxy, do WAF e da aplicação; antivírus, VPN ou filtragem no lado do cliente. |
| ERR_CONNECTION_TIMED_OUT (-118) | O SYN do TCP saiu e nada voltou até o cliente desistir. | Firewalls que descartam pacotes, e se o host está no ar. |
O que causa o ERR_QUIC_PROTOCOL_ERROR
- A UDP 443 está filtrada ou limitada. Um firewall, roteador ou produto de segurança deixa passar os primeiros pacotes e descarta os seguintes, ou limita a taxa de UDP. Alguns firewalls corporativos tratam o QUIC como tráfego desconhecido.
- O caminho descarta pacotes grandes. A RFC 9000 exige datagramas UDP de pelo menos 1200 bytes nos primeiros pacotes do QUIC. Uma VPN, um túnel ou um link PPPoE com MTU pequena, ou um dispositivo que descarta fragmentos, quebra isso.
- NAT e timeouts de ociosidade. Um dispositivo de NAT esquece um mapeamento UDP depois de pouco tempo ocioso, e os pacotes do servidor passam a ir para lugar nenhum.
- Uma VPN, proxy ou antivírus que lida mal com UDP. O software no dispositivo pode bloquear, inspecionar ou reescrever o tráfego UDP.
- O servidor perde o estado. Depois de uma reinicialização ou de uma queda, o servidor não tem registro das conexões antigas. A RFC 9000 descreve o stateless reset para esse caso, e o cliente vê a conexão terminar.
- Um balanceador de carga que não entende QUIC. Os pacotes de uma conexão precisam chegar ao mesmo backend. Balancear só por endereço e porta de origem pode falhar quando um NAT muda a porta do cliente.
- O HTTP/3 é anunciado mas não é alcançável. O servidor envia
Alt-Svc, mas a UDP 443 está fechada num firewall, num grupo de segurança da nuvem ou num mapeamento de porta do Docker. - Bugs numa implementação de HTTP/3. Um servidor ou nó de CDN que envia cabeçalhos ou frames inválidos, ou um navegador antigo, pode encerrar uma conexão com um erro de protocolo.
- Flags e extensões do Chrome. Flags experimentais e extensões que mudam o comportamento da rede podem interferir.
Causas no servidor e configuração
Se você administra o site, confira se o HTTP/3 funciona de ponta a ponta, da internet até o processo que responde, ou desative-o de forma limpa.
Encontre o erro QUIC num log do Chrome
Abra chrome://net-export, clique em “Start Logging to Disk”, reproduza o erro, clique em “Stop Logging” e abra o arquivo no visualizador NetLog para o qual a página aponta. Procure o evento QUIC_SESSION_CLOSED. O campo quic_error dele nomeia o motivo, e from_peer diz se foi o servidor que encerrou a conexão. Estes valores da biblioteca QUIC do Chromium são comuns:
| quic_error | Significado na biblioteca | Onde olhar primeiro |
|---|---|---|
QUIC_TOO_MANY_RTOS | O QUIC deu timeout depois de timeouts de retransmissão demais: pacotes foram enviados e nunca confirmados. | Perda de pacotes no caminho UDP: firewall, NAT, MTU, um servidor sobrecarregado. |
QUIC_NETWORK_IDLE_TIMEOUT | A conexão deu timeout por falta de atividade na rede. | Mapeamentos de NAT que expiram, ou um caminho que descarta pacotes sem nenhuma resposta. |
QUIC_PUBLIC_RESET | Um reset desta conexão foi recebido. | Uma reinicialização do servidor, ou um balanceador de carga que enviou pacotes para outro backend. |
QUIC_PACKET_WRITE_ERROR | Ocorreu um erro ao escrever no socket. | A pilha de rede do dispositivo: VPN, driver de firewall, adaptador. |
Abra a UDP 443 em todas as camadas
Para firewalls, TCP 443 e UDP 443 são portas diferentes. Confira cada camada que tem regras próprias:
# Há algo escutando na 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: publique a porta UDP junto com a porta TCP
docker run -d -p 443:443/tcp -p 443:443/udp my-web-image
Em grupos de segurança e ACLs de rede na nuvem, adicione uma regra de entrada para a UDP 443. No Kubernetes, um Service precisa de uma entrada de porta própria para 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
A documentação do nginx lista suporte a HTTP/3 desde a versão 1.25.0, com o módulo marcado como experimental. Ela recomenda a mesma porta para HTTP/3 e HTTPS. O listener precisa do parâmetro quic, e a resposta precisa do cabeçalho Alt-Svc:
server {
listen 443 quic reuseport; # HTTP/3 sobre UDP
listen 443 ssl; # HTTPS sobre 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;
}
O valor ma é por quanto tempo, em segundos, os clientes podem lembrar do serviço HTTP/3 (86400 são 24 horas). Para desligar o HTTP/3, remova o listener quic e o cabeçalho Alt-Svc. Os clientes que lembravam do cabeçalho antigo continuam tentando até o ma acabar. Envie add_header Alt-Svc 'clear' always; por um tempo: a RFC 7838 define clear para invalidar todos os serviços alternativos da origem. O log de debug do nginx marca todas as mensagens QUIC com o prefixo “quic”, o que facilita filtrá-las.
Caddy
O Caddy serve HTTP/3 por padrão. A documentação dele lista h1 h2 h3 como padrão da opção protocols. Para desligar o HTTP/3, defina a lista sem h3:
{
servers {
protocols h1 h2
}
}
CDNs e balanceadores de carga
A maioria dos CDNs tem uma chave para o HTTP/3 nas configurações de rede. Se os erros começaram depois de uma mudança no CDN ou no balanceador de carga, desligue o HTTP/3 ali primeiro e veja se eles param. Nos seus próprios balanceadores de carga UDP, garanta que os pacotes de uma conexão QUIC cheguem ao mesmo backend mesmo quando a porta de origem do cliente muda.
Como aparece visto de fora
- Funciona por HTTP/2 e falha por HTTP/3, de todos os locais: a pilha HTTP/3 do servidor ou do CDN é a culpada. Desligue o HTTP/3 nessa camada enquanto investiga.
- Falha só em algumas redes: um firewall ou provedor nessas redes trata mal a UDP 443. O servidor está bem, e o Chrome volta para o TCP na maioria dos casos.
- Falha só para você, enquanto outros navegadores ou dispositivos funcionam: a causa está no seu dispositivo ou roteador, como software de segurança, uma VPN, uma flag do Chrome ou uma extensão.
- Arquivos grandes e respostas longas falham, páginas pequenas carregam: a falha acontece depois que os cabeçalhos chegaram, então o Chrome não consegue tentar de novo. Procure problemas de MTU, limites de taxa de UDP e timeouts de ociosidade.
- Os erros aparecem depois de deploys ou reinicializações: o servidor perdeu o estado das conexões, ou o balanceador de carga moveu conexões.
A UDP 443 é um caminho de rede separado da TCP 443, então uma página que carrega por TCP não diz nada sobre o HTTP/3. Teste o HTTP/3 diretamente com os comandos curl acima e compare com o verificador HTTP, que confere o status HTTP, o tempo de resposta e a disponibilidade do servidor de um host a partir de locais do mundo todo.
Como corrigir o ERR_QUIC_PROTOCOL_ERROR
Se você é o visitante
- Recarregue a página. O Chrome muitas vezes tenta de novo por TCP sozinho e lembra que o HTTP/3 falhou naquele site.
- Tente outra rede e desligue a VPN. Se o site funciona nos dados móveis, a primeira rede ou a VPN bloqueia ou deforma o UDP.
- Atualize o Chrome em
chrome://settings/helpe reinicie-o. - Desative o QUIC no Chrome. Abra
chrome://flags/#enable-quic, mude “Experimental QUIC protocol” para “Disabled” e clique no botão de reiniciar (“Relaunch”). O nome e a posição dessa flag podem mudar entre versões do Chrome, então procure por “QUIC” emchrome://flagsse não a encontrar. O Edge e outros navegadores baseados em Chromium têm a própria página de flags, por exemploedge://flags. Os sites continuam funcionando por TCP. - Inicie o Chrome sem QUIC se preferir uma opção de linha de comando. No Windows, execute
chrome.exe --disable-quica partir da pasta de instalação. No macOS, executeopen -a "Google Chrome" --args --disable-quic. No Linux, executegoogle-chrome --disable-quic. - Desative as extensões ou use uma janela anônima. Se o erro desaparecer, reative as extensões uma de cada vez.
- Confira o software de segurança e o roteador. Alguns produtos bloqueiam ou inspecionam o QUIC. Num computador corporativo, peça à equipe de TI para liberar a UDP 443 ou para definir a política do Chrome
QuicAllowedcomo false, o que proíbe o QUIC.
Se você administra o site
- Confira o que você anuncia:
curl -sI https://example.com/ | grep -i alt-svc. - Compare o HTTP/3 com o HTTP/2 usando os dois comandos curl acima, a partir da sua própria rede e de um servidor em outra rede.
- Abra a UDP 443 no firewall do host, no grupo de segurança da nuvem, no mapeamento do contêiner e no balanceador de carga, e confira o listener com
ss -lunp. - Leia os logs do servidor em busca de erros QUIC no horário da falha, e atualize o servidor web e a biblioteca TLS dele para as versões que o fornecedor lista para HTTP/3.
- Se não conseguir corrigir rápido, desligue o HTTP/3 no CDN ou no servidor web e envie
Alt-Svc: clearpor um tempo. Os visitantes passam a usar HTTP/2 sobre TCP. - Verifique com a coluna Protocol no DevTools depois de cada mudança.
Monitorando um site que oferece HTTP/3
Um problema de HTTP/3 muitas vezes afeta algumas redes e regiões e outras não, então o padrão importa mais que um resultado isolado. A HostTracker monitora sites desde 2004 e os verifica a partir de mais de 300 pontos de verificação em 158 cidades, com alertas por e-mail, SMS, chamada de voz, Slack, Telegram e mais. Depois de toda mudança em firewalls, balanceadores de carga ou configurações de CDN, teste também a UDP 443 diretamente com o curl, porque ela é um caminho separado.
Perguntas frequentes
Qual a diferença entre QUIC e HTTP/3?
O QUIC é um protocolo de transporte que roda sobre UDP e é definido na RFC 9000. O HTTP/3 é a versão do HTTP que roda sobre o QUIC, definida na RFC 9114. Os dois são criptografados: o HTTP/3 usa TLS 1.3 dentro do QUIC, e os navegadores só usam HTTP/2 sobre TLS em TCP.
É seguro desativar o QUIC no Chrome?
Sim. Os sites continuam funcionando por HTTP/2 ou HTTP/1.1 sobre TCP, e esse tráfego também é criptografado com TLS. Você só perde os recursos do HTTP/3.
O ERR_QUIC_PROTOCOL_ERROR significa que o site está fora do ar?
Não. O mesmo site normalmente continua funcionando por TCP. O erro diz que a conexão HTTP/3 falhou pelo caminho, e a causa pode ser a sua rede, o servidor ou qualquer coisa entre os dois.
Por que só acontece com arquivos grandes?
O Chrome só pode repetir uma requisição por TCP antes de os cabeçalhos da resposta chegarem. Uma falha no meio de um corpo grande não deixa nada para repetir, e a página de erro ou a mensagem no console aparece. Perda de pacotes, limites de MTU e timeouts de ociosidade afetam transferências longas com mais frequência.
Por que vejo isso no Chrome e no Edge, mas não no Firefox?
O Chrome e o Edge compartilham a pilha de rede do Chromium e seus códigos de erro. O Firefox tem a própria implementação de HTTP/3 e as próprias mensagens de erro, então o mesmo problema de rede aparece de outra forma ali.
Preciso de HTTP/3 no meu servidor?
Não. O HTTP/3 é opcional, e o HTTP/2 sobre TCP funciona em todos os navegadores. Se você não consegue manter a UDP 443 confiável de ponta a ponta, desativar o HTTP/3 é uma escolha válida.
Fontes e leitura adicional
- Chromium net error list: as definições de QUIC_PROTOCOL_ERROR (-356), QUIC_HANDSHAKE_FAILED (-358) e dos outros códigos da tabela acima.
- RFC 9114, HTTP/3: a seção 3.1 sobre descobrir um endpoint HTTP/3 e voltar para o TCP, e a seção 3.1.1 sobre o cabeçalho Alt-Svc.
- RFC 9000, QUIC: a seção 14.1 sobre o tamanho de datagrama de 1200 bytes, e a seção 10.3 sobre o stateless reset.
- nginx: ngx_http_v3_module: o listener
quic, o exemplo deAlt-Svce as diretivas de HTTP/3.