A listagem própria de erros de rede do Chromium descreve este numa única frase:

O cliente escolheu bloquear o pedido.

A palavra que carrega o peso é escolheu. Nada falhou. Nenhum servidor estava em baixo, nenhum nome foi deixado de resolver, nenhum certificado estava errado. Algo a correr na própria máquina do visitante viu um pedido que a sua página estava prestes a fazer e decidiu que não seria feito.

O que quer dizer que o seu servidor nunca o viu. Não há linha no seu registo de acesso, nenhuma entrada no seu rastreador de erros, e nada para encontrar da sua parte, porque do ponto de vista da infraestrutura nenhuma requisição foi enviada.

Quem é o cliente

Geralmente uma extensão. Os bloqueadores de anúncios e rastreadores são o caso comum, e estão instalados muito mais amplamente do que a maioria das equipas assume quando olham para as suas próprias máquinas.

Mas a categoria é mais larga do que isso. O software de segurança empresarial de ponto final filtra pedidos antes de saírem da máquina. Alguns produtos antivírus fazem o mesmo. Uma configuração de proxy corporativo pode recusar um host. As definições do navegador num dispositivo gerido podem bloquear uma categoria completamente. Todos estes produzem o mesmo erro, e nenhum deles é algo que a pessoa que reporta o problema saiba que tem.

A coisa que todos partilham é que ficam entre o seu código e a rede, dentro do ambiente do utilizador, onde você não tem visibilidade e nenhum controlo.

Três erros que todos dizem bloqueado

O Chromium tem vários, não são intercambiáveis, e a diferença é inteiramente sobre quem fez o bloqueio. Estes são os três que vale a pena conhecer, com as descrições da própria lista de erros:

  • ERR_BLOCKED_BY_CLIENT: “O cliente escolheu bloquear o pedido.” Algo na máquina do utilizador. Não a sua, e não a do outro site.
  • ERR_BLOCKED_BY_CSP: “O pedido foi bloqueado por uma política de segurança de conteúdo.” A sua própria política, ou uma que um proxy adicionou pelo caminho.
  • ERR_BLOCKED_BY_RESPONSE: a resposta chegou com requisitos que não foram cumpridos, como X-Frame-Options, verificações de antepassados de Content-Security-Policy ou Cross-Origin-Resource-Policy. Esse é a decisão do outro lado.

Três erros, três proprietários: a máquina do utilizador, a sua política, os seus cabeçalhos. Apenas o do meio é seu para corrigir, e é aquele para o qual as pessoas vão por último. Uma quarta família confunde-se com estas frequentemente o suficiente para valer a pena separar também: um erro CORS não é um bloqueio de todo, é uma resposta que o navegador foi buscar e depois se recusou a entregar ao seu código.

O que o seu JavaScript vê, o qual é quase nada

Aqui está a parte que torna isto dispendioso. Um pedido bloqueado não chega ao seu código como “bloqueado”.

fetch() é rejeitado com um TypeError, e MDN é explícito que isto é o que se obtém para um erro de rede em geral, “por exemplo, porque o dispositivo não tem conectividade”. A mesma rejeição cobre um URL mal formado, um dispositivo realmente sem ligação, e um pedido que uma extensão se recusou a enviar. A promessa não carrega nenhuma razão, por isso não há nada na rejeição que os distinga.

Vale a pena lembrar o que não é rejeitado enquanto está aqui: um estado de erro HTTP não é. Um 404 ou um 504 resolve normalmente e deixa-o a verificar response.ok. Então a falha que produz a informação menos útil no seu código é aquela onde o pedido nunca saiu da máquina, e as falhas que produzem a informação mais útil são aquelas que o seu servidor tratou.

Se quer a distinção, o navegador tem-a. O painel de rede mostra o pedido com o erro de rede contra ele, e chrome://net-export captura-o. Ambos estão no computador do utilizador, que é o problema de que este artigo inteiro fala.

Porque é tão difícil reproduzir

Não pode reproduzi-lo, por construção, porque a causa não está no seu sistema. Está numa configuração que existe numa máquina, escolhida por alguém que pode não se lembrar de ter escolhido, e muito possivelmente instalada pelo seu empregador.

Então o ciclo vai assim: um utilizador reporta que guardar não faz nada, você abre a página, guardar funciona, você fecha o ticket. O utilizador não está enganado e nem você. A diferença é uma lista de hosts bloqueados que não consegue ver.

Pedir-lhes que desativem extensões às vezes funciona e é um instrumento pobre. Pede a uma pessoa que faça experiências no seu próprio navegador em seu favor, só encontra o caso de extensão, e um dispositivo gerido nem os deixará fazê-lo.

Session Replay

Extensão gratuita do Chrome. Um clique na página que se está a portar mal captura a captura de ecrã, a consola e o registo de rede, e devolve-lhe um link para colar no ticket.

Instalar a extensão

O registo de rede é o que o resolve, porque o pedido que foi recusado está nele com o erro contra ele. Isso transforma “guardar não faz nada” em “este pedido para este host nunca saiu da sua máquina”, o qual é uma conversa diferente e geralmente uma curta.

O que fazer a respeito

Espere isto em qualquer coisa que pareça rastreamento. Os hosts com análise, métricas, telemetria, beacon ou anúncios no nome são bloqueados por defeito por listas comuns. O mesmo com caminhos. Se o seu próprio relatório de erro vive num tal host, os relatórios sobre ele são aqueles que nunca receberá.

Não deixe que um pedido bloqueado quebre a página. Uma chamada de análise bloqueada não deve parar um formulário de ser enviado. Separe o pedido que importa do pedido que é agradável de ter, e deixe o segundo falhar em silêncio.

Trate a ausência de dados como dados. Menos eventos de um subconjunto de utilizadores é um dos poucos sinais que isto deixa para trás, e parece uma semana quieta em vez de uma falha.

Num parágrafo

ERR_BLOCKED_BY_CLIENT significa que algo na máquina do visitante, geralmente uma extensão e às vezes o software do seu empregador, decidiu que o seu pedido não seria enviado. O seu servidor nunca o viu, fetch reporta-o como o mesmo TypeError que usa para um dispositivo sem ligação, e o único registo está num computador que não tem. Não é o mesmo que um bloqueio de política seu ou um cabeçalho que o outro lado enviou, e distinguir estes três é a maior parte do trabalho.