O Error.isError() do JavaScript Explicado
Error.isError() verifica erros reais de JavaScript entre realms, explica por que supera instanceof Error e mostra um fallback seguro.
Error.isError(value) é um método estático que retorna true apenas quando value é um objeto Error genuíno, e permanece confiável mesmo entre realms, porque verifica uma marca interna ([[ErrorData]]) em vez de percorrer a cadeia de protótipos.
Se você já abriu seu rastreador de erros e encontrou um {} vazio onde deveria haver uma exceção real, você já conheceu o problema que isso resolve. Em algum ponto do caminho, uma verificação instanceof silenciosamente decidiu que seu erro não era um erro. O método foi padronizado no ECMAScript 2026, o que significa que as lacunas históricas do instanceof Error (erros vindos de iframes que são lidos como não-erros e objetos falsos que são lidos como erros) agora têm uma solução de primeira classe. Este artigo explica o que o método faz, por que ele supera o instanceof, o mecanismo exato por trás dele, seus casos extremos e como adotá-lo com um fallback seguro.
O comportamento é exatamente o que você esperaria: Error.isError(new Error()) é true, e Error.isError({ message: 'x' }) é false, porque o método verifica como o objeto foi construído, e não meramente o que ele herda.
Principais Conclusões
Error.isError()executa uma verificação de marca (branded check) pelo slot interno[[ErrorData]], a mesma categoria de verificação infalsificável queArray.isArray()usa, de modo que código em userland não consegue burlá-la.instanceof Errorfalha de duas maneiras opostas:falsepara um erro real criado em outro realm, etruepara um objeto falso cujo protótipo foi definido comoError.prototype.- O método retorna
truepara subclasses nativas comoTypeError, para classes que corretamente fazemextend Error, e paraDOMExceptionnos navegadores, embora o Safari atualmente retornefalseparaDOMException. Error.isError()faz parte do ECMAScript 2026 e está disponível no Chrome/Edge 134+, Firefox 138+, Node.js 24.0.0+ e Safari 18.4 (parcial).- Use-o em fronteiras (handlers globais, camadas de logging, workers, iframes, SSR/edge) onde uma falha silenciosa do
instanceoftransforma um erro real em um objeto vazio nos seus logs.
Por que instanceof Error é insuficiente?
Discover how at OpenReplay.com.
instanceof Error falha de duas maneiras opostas, e ambas são silenciosas. A proposta do TC39 detalha a primeira: um erro genuíno que cruzou uma fronteira de realm, seja vindo de um iframe ou do módulo vm do Node, retorna um falso negativo. Cada realm tem seu próprio construtor Error, então um erro criado em um iframe não é uma instância do seu Error.
A segunda falha é o inverso: qualquer objeto com Error.prototype em sua cadeia passa na verificação sem ser um erro real. Veja cada falha em código:
// Failure 1 — cross-realm error reads as NOT an error
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const crossRealmError = new iframe.contentWindow.Error('from iframe');
crossRealmError instanceof Error; // → false (wrong)
Error.isError(crossRealmError); // → true (correct)
// Failure 2 — fake object reads as an error
const fake = { message: "I'm not real" };
Object.setPrototypeOf(fake, Error.prototype);
fake instanceof Error; // → true (wrong)
Error.isError(fake); // → false (correct)
Ambos os resultados fazem parte do contrato documentado, e não são um acidente. A referência do MDN para o método o apresenta como a alternativa robusta ao instanceof Error justamente porque ele evita cada um desses modos de falha: um protótipo emprestado não é suficiente para passar na verificação, e um erro construído em outro realm ainda assim passa. O instanceof compara a identidade do construtor ao longo da cadeia de protótipos, e por isso erra em ambos os casos.
| Entrada | instanceof Error | duck-typing ('message' in x) | Error.isError() |
|---|---|---|---|
Error cross-realm (iframe/worker/vm) | ❌ false | ⚠️ depende | ✅ true |
Object.setPrototypeOf(obj, Error.prototype) | ❌ true | ⚠️ true | ✅ false |
Instância de class MyError extends Error | ✅ true | ✅ true | ✅ true |
Como o Error.isError() funciona internamente?
Internamente, Error.isError() executa uma verificação de marca (branded check) por um slot interno, em vez de inspecionar a cadeia de protótipos. O MDN descreve o mecanismo diretamente: o método procura por um campo privado que o construtor Error() instala em todo erro que constrói. Esse é o mesmo truque por trás de Array.isArray(), e um parente próximo de como o operador in testa a existência de uma propriedade.
Essa analogia com Array.isArray() é o modelo mental a manter. Array.isArray() também aceita arrays construídos em um realm diferente, onde instanceof Array reporta false porque cada realm possui um construtor Array separado. Error.isError() traz essa mesma marcação segura entre realms para os erros.
O texto da especificação em Stage 4 nomeia o slot como [[ErrorData]] e mantém a operação IsError em três passos: qualquer coisa que não seja um objeto falha imediatamente, qualquer coisa que carregue o slot passa, e todo o resto falha. O slot é definido na construção e não pode ser forjado a partir do JavaScript.
Por que um slot em vez de Object.prototype.toString? Porque a falsificação de tags quebrou o truque antigo. O autor da proposta levou o problema ao comitê: uma vez que o Symbol.toStringTag passou a existir, uma verificação que era ao mesmo tempo confiável e impossível de falsificar deixou de ser ambas as coisas. E como nada fora do Object#toString jamais consultava o slot de erro, o código de usuário ficou sem nenhum teste confiável. Error.isError() preenche exatamente essa lacuna.
Detalhes de comportamento que vale conhecer
Error.isError() retorna true para toda a família de erros e false para todo o resto, sem lançar exceções. Os exemplos do MDN mostram new Error(), new TypeError() e new DOMException() retornando true, enquanto uma chamada sem argumento, ou passando {}, null, undefined, 17 ou a string "Error", retorna false. Como o predicado da especificação retorna false para qualquer não-objeto e para objetos sem o slot, primitivos e null são tratados de forma limpa, sem gerar exceções.
Classes personalizadas corretamente estendidas são detectadas, já que herdam a marca:
class ValidationError extends Error {}
Error.isError(new ValidationError('bad input')); // → true
Apenas os sósias que nunca chamam o construtor Error são rejeitados. O caso do DOMException tem uma nuance que vale memorizar. A regra do MDN é que instâncias de DOMException passam. DOMException não é formalmente uma subclasse de Error, porque seu construtor não herda do construtor Error, mas carrega a mesma marca, então verificações por marca a tratam como um erro de qualquer forma. O Safari é a exceção: o resumo do mês em que o Firefox 138 foi lançado, publicado pelo Chrome, registra que o Safari responde false para DOMException, e é por isso que o método ainda não alcançou o status Baseline, mesmo que todos os principais engines já o implementem. O MDN ainda o classifica como de disponibilidade limitada pelo mesmo motivo. Trate esse caso específico como algo ainda não uniforme.
Quando usar Error.isError()
Use Error.isError() em fronteiras (handlers globais de erro, camadas de logging e de reporte de erros, test runners, bibliotecas, SSR/edge, workers, iframes e extensões de navegador) onde uma falha silenciosa do instanceof transforma um erro real em um {} vazio nos seus logs. O instanceof puro é adequado em código restrito e dentro do mesmo realm; o ganho está especificamente nas bordas, onde valores cruzam contextos de execução.
Isso corresponde a um modo real de falha no reporte: uma verificação instanceof em uma fronteira reclassifica um erro genuinamente lançado como um objeto comum, então ele chega ao seu pipeline sem mensagem nem stack. A repetição de sessão (session replay) é uma técnica útil aqui: reproduzir a sessão revela o erro de console que foi realmente lançado, expondo a lacuna entre o que o navegador viu e o que sua camada de integração reportou. A correção é fazer a verificação por marca com Error.isError() nessas fronteiras, antes que qualquer coisa seja serializada ou registrada.
Suporte em navegadores e runtimes, e um fallback seguro
Error.isError() faz parte do ECMAScript 2026, a 17ª edição, que a Ecma International ratificou em 30 de junho de 2026; a proposta alcançou o Stage 4 na reunião do TC39 de maio de 2025. Nos navegadores, funciona a partir do Chrome e Edge 134, Safari 18.4 e Firefox 138, lançado em 29 de abril de 2025. No servidor, o Node.js 24.0.0 o incorporou por meio da atualização para o V8 13.6, que o trouxe junto com Float16Array, gerenciamento explícito de recursos, RegExp.escape e WebAssembly Memory64.
Para uma atualização plug-and-play que degrada graciosamente em alvos mais antigos, faça detecção de recurso:
function isError(value) {
return typeof Error.isError === 'function'
? Error.isError(value) // realm-safe on modern engines
: value instanceof Error; // fallback, not realm-safe
}
No TypeScript, Error.isError(e) também atua como um type guard, estreitando um valor capturado do tipo unknown para Error dentro do bloco if, de modo que e.message seja type-safe sem um cast manual.
Conclusão
Error.isError() fecha uma lacuna que nem o duck-typing nem o instanceof conseguiram fechar: ele pergunta se o engine realmente marcou um valor como erro, então tanto erros cross-realm quanto falsificações por protótipo são resolvidos corretamente. Migre hoje mesmo suas verificações de fronteira (a camada de logging, os handlers globais, as junções com workers e iframes) para o wrapper com detecção de recurso, e mantenha o instanceof apenas onde o código nunca sai do próprio realm.
Perguntas Frequentes
O Error.isError() está padronizado ou ainda é uma proposta experimental?
Error.isError() está totalmente padronizado. Ele avançou para o Stage 4 do processo do TC39 na 108ª reunião, em maio de 2025, e está incluído no ECMAScript 2026, a 17ª edição da especificação da linguagem. Não é mais uma proposta nem um recurso experimental, portanto descrições que o chamam de 'ainda não padronizado' ou 'Stage 3' estão desatualizadas. Trate-o como um recurso já lançado da linguagem.
O Error.isError() funciona com classes de erro personalizadas?
Sim, desde que a classe estenda Error corretamente. Uma classe definida como 'class MyError extends Error {}' herda a marca interna definida pelo construtor Error, então Error.isError(new MyError()) retorna true. Apenas objetos sósias que nunca chamam o construtor Error, como um objeto comum com Error.prototype forçado em sua cadeia, são rejeitados. O requisito é a herança correta, não o nome da classe.
O Error.isError() funciona no Safari?
O Safari 18.4 e versões posteriores suportam Error.isError() para objetos Error comuns, mas o suporte é parcial. O Safari atualmente retorna false para instâncias de DOMException, enquanto a especificação e os demais engines retornam true. Por causa dessa lacuna, o MDN não classifica o método como Baseline, e o web.dev o sinaliza como ainda não uniformemente disponível. Trate o caso do DOMException de forma defensiva se seu código tiver o Safari como alvo.
O Error.isError() é mais rápido que instanceof Error?
Ambos são, na prática, verificações de tempo constante, então desempenho não é o motivo para migrar. O instanceof percorre a cadeia de protótipos enquanto o Error.isError() lê uma única marca interna, mas a diferença prática é insignificante. A verdadeira vantagem é a correção: Error.isError() dá a resposta certa para erros cross-realm e falsificações por protótipo, casos em que o instanceof falha silenciosamente. Escolha-o pela confiabilidade nas fronteiras de contexto de execução, não pela velocidade.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Star on GitHub12k