JavaScript Errors

Tratamento de Erros em JavaScript

Coisas dão errado. Redes caem, inputs surpreendem e APIs mudam. Um bom tratamento de erros evita que essas falhas se tornem interrupções no serviço e usuários irritados.

intermediate14 min readUpdated 15 de set. de 2026
js
// api.js
class HttpError extends Error {
  constructor(status) {
    super(`Request failed with status ${status}`);
    this.name = "HttpError";
    this.status = status;
  }
}

try {
  const res = await fetch("/api/data");
  if (!res.ok) throw new HttpError(res.status);
  const data = await res.json();
} catch (error) {
  if (error instanceof HttpError) report(error.status);
  else console.error(error);
}
Tipo base
Error
Lançar com
throw
Tratar com
try / catch / finally
Estender com
class extends Error
Async
try/catch + rejected promises
Rede de segurança
Global error handlers

Pratico

Try, catch e finally

Altere o número para disparar o erro e observe a ordem das mensagens.

Try, catch e finally

Altere o número para disparar o erro e observe a ordem das mensagens.

Por que importa

Por que o tratamento de erros é importante

Falhe graciosamente

Um erro tratado mantém o app funcionando e mostra algo útil ao usuário em vez de uma tela em branco.

Debugue mais rápido

Bons erros carregam uma mensagem, um tipo e um stack trace, transformando um mistério em uma correção de cinco minutos.

Construa confiança

Recuperações claras e mensagens honestas fazem o app parecer sólido, mesmo quando a rede não está.

O panorama completo

Três perguntas que toda falha faz

Um bom tratamento de erros responde às mesmas três perguntas todas as vezes: o que deu errado, quem deve saber e o que acontece a seguir.

Detecção

O que deu errado

Lance erros precisos e tipados no ponto da falha, em vez de deixar um estado inválido se propagar.

Recuperação

Quem trata

Capture o erro onde você possa fazer algo significativo e deixe todo o resto subir (bubble up).

Comunicação

O que acontece a seguir

Diga ao usuário o que ele pode fazer, registre os detalhes para os desenvolvedores e mantenha o app vivo.

Tratamento de erros em resumo

As ferramentas que você usará

Objetos Error

message, name, stack e cause — a estrutura nativa de uma falha.

throw

Lance seus próprios erros no momento em que uma regra é quebrada.

try / catch

Envolva códigos arriscados e trate a falha sem travar a aplicação.

finally

Limpeza que é executada independentemente de a tentativa ter tido sucesso ou falhado.

Erros personalizados

Subclasses de Error que carregam dados específicos do domínio.

Erros assíncronos

Promises rejeitadas e try/catch em torno de await.

Uma breve historia

Como o JavaScript aprendeu a falhar bem

  1. 1995

    Erros sobre erros

    O JavaScript primitivo expõe window.onerror como a única rede de segurança global.

    95
  2. 1999

    Chegada do try / catch

    O ES3 traz o tratamento estruturado de exceções para a linguagem.

    99
  3. 2015

    Promises e rejections

    O ES6 torna as rejeições de promises não tratadas uma nova classe de falhas a serem gerenciadas.

    15
  4. 2021

    error.cause

    Erros agora podem envolver a causa subjacente, preservando o contexto original.

    21
  5. Hoje

    Cultura de Error-first

    Ferramentas, linters e frameworks assumem um tratamento de erros explícito e tipado.

    Hoje

O guia completo

Tratamento de Erros em JavaScript: Tudo que voce precisa saber

Por que erros são inevitáveis

Todo programa eventualmente encontra uma situação inesperada: um servidor retorna um 500, um usuário digita letras em um campo numérico, um arquivo está faltando ou uma API de terceiros muda sua estrutura. O tratamento de erros não serve para evitar todas as falhas — mas sim para decidir o que acontece quando uma delas ocorre.

Erros bem tratados mantêm a aplicação funcionando, informam algo útil ao usuário e fornecem aos desenvolvedores os detalhes necessários. Erros mal tratados resultam em telas em branco, perda silenciosa de dados e relatórios de bugs impossíveis de reproduzir.

O objeto Error

O JavaScript possui um tipo Error nativo, e todo erro lançado geralmente é uma instância dele.

// error.js
const error = new Error("Something broke");

error.message; // "Something broke"
error.name;    // "Error"
error.stack;   // the call stack at the point of creation
error.cause;   // an optional underlying error

Existem diversas subclasses nativas para categorias comuns: TypeError, ReferenceError, RangeError, SyntaxError, URIError e EvalError. Elas diferem principalmente no nome e nas situações que as produzem, o que as torna úteis para depuração e para criar ramificações baseadas no tipo de falha.

Lançando erros

Use throw para sinalizar que uma regra foi violada. Lance um objeto Error, nunca uma string ou um número — apenas instâncias de Error carregam uma mensagem, um nome e um stack trace.

// validate.js
function divide(a, b) {
  if (b === 0) {
    throw new Error("Cannot divide by zero");
  }
  return a / b;
}

Lançar erros precocemente, no ponto exato onde uma premissa é quebrada, evita que estados inválidos se propaguem profundamente em seu programa. Falhar ruidosamente durante o desenvolvimento é um recurso, não um incômodo.

try, catch e finally

O try executa código arriscado. Se algo lançar um erro, o controle salta para o catch. O finally é executado de qualquer maneira, o que o torna o lugar ideal para a limpeza (cleanup).

// try.js
try {
  const data = JSON.parse(input);
  save(data);
} catch (error) {
  console.error("Invalid data:", error.message);
} finally {
  setLoading(false);
}

O parâmetro catch é o valor lançado. O JavaScript moderno também suporta optional catch binding quando você não precisa dele: catch { ... }. Dentro de um bloco catch, você pode inspecionar o erro, registrá-lo em logs, recuperar a execução ou relançá-lo caso não consiga tratá-lo.

// rethrow.js
try {
  await loadProfile();
} catch (error) {
  log(error);
  throw error; // let a higher layer decide
}

Classes de erro customizadas

Erros genéricos perdem o sentido à medida que sua aplicação cresce. Classes customizadas permitem que você anexe contexto e crie ramificações baseadas no tipo de falha.

// http-error.js
class HttpError extends Error {
  constructor(status, message) {
    super(message ?? `HTTP ${status}`);
    this.name = "HttpError";
    this.status = status;
  }
}

class ValidationError extends Error {
  constructor(field, message) {
    super(message);
    this.name = "ValidationError";
    this.field = field;
  }
}

Agora, quem chama a função pode reagir com precisão:

// handle.js
try {
  await save(form);
} catch (error) {
  if (error instanceof ValidationError) {
    showFieldError(error.field, error.message);
  } else if (error instanceof HttpError && error.status === 401) {
    redirectToLogin();
  } else {
    showGenericError();
  }
}

Esta é a diferença entre “algo deu errado” e “o campo de e-mail já está sendo utilizado”.

Envolvendo erros com cause

Às vezes, você deseja adicionar contexto sem perder a falha original. A opção cause preserva a cadeia de erros.

// cause.js
try {
  await db.query(sql);
} catch (error) {
  throw new Error("Failed to load orders", { cause: error });
}

O erro externo carrega o contexto amigável para o usuário, enquanto o error.cause mantém os detalhes originais para logs e depuração.

Erros em código assíncrono

O código assíncrono possui dois caminhos de falha adicionais. Com async/await, try/catch funciona exatamente como no código síncrono.

// async.js
async function load() {
  try {
    const res = await fetch("/api/data");
    if (!res.ok) throw new HttpError(res.status);
    return await res.json();
  } catch (error) {
    console.error("Load failed:", error);
    throw error;
  }
}

Sem await, anexe um handler à promise:

// promise.js
fetch("/api/data")
  .then((res) => res.json())
  .catch((error) => console.error(error));

Uma promise rejeitada sem um handler torna-se uma unhandled rejection. Nos navegadores, isso gera um aviso no log; no Node.js, isso pode encerrar o processo. Sempre trate as rejeições, mesmo que seja apenas para registrar o log e relançar o erro.

Redes de segurança globais

Mesmo com um código cuidadoso, algo acabará passando. Handlers globais capturam o que você deixou escapar para que o app possa reportar o erro em vez de morrer silenciosamente.

// global.js
window.addEventListener("error", (event) => {
  reportToServer(event.error);
});

window.addEventListener("unhandledrejection", (event) => {
  reportToServer(event.reason);
});

No Node.js, os equivalentes são process.on("uncaughtException") e process.on("unhandledRejection"). Trate-os como último recurso para logging e shutdown gracioso, e não como um substituto para o tratamento de erros onde eles ocorrem.

Valide antes de lançar

Nem todo problema é excepcional. Condições esperadas — entrada vazia, um campo opcional ausente, uma busca sem resultados — são melhor tratadas com validação do que com exceções.

// guards.js
function formatName(user) {
  if (!user?.name) return "Anonymous";
  return user.name.trim();
}

Reserve as exceções para situações genuinamente inesperadas ou irrecuperáveis. Usá-las para o fluxo de controle comum torna o código mais lento e difícil de acompanhar.

Falando com os usuários

Uma mensagem de erro técnica é voltada para desenvolvedores. Os usuários precisam saber o que aconteceu e o que podem fazer a seguir.

  • Mantenha as mensagens curtas e humanas: “Não foi possível salvar suas alterações. Verifique sua conexão e tente novamente.”
  • Evite jargões, stack traces e códigos de status brutos na interface.
  • Forneça um próximo passo: tentar novamente, voltar, entrar em contato com o suporte ou continuar offline.
  • Registre todos os detalhes — mensagem, stack, contexto — para que o suporte possa investigar.

Melhores práticas

  • Lance objetos Error, nunca strings.
  • Use o catch apenas onde for possível recuperar o erro ou adicionar contexto útil.
  • Utilize classes de erro customizadas para falhas específicas do domínio.
  • Envolva erros com cause em vez de descartar o original.
  • Sempre trate as rejeições de promises.
  • Adicione handlers globais como uma rede de segurança final e envie os logs para um serviço real.
  • Valide as condições esperadas em vez de apenas lançar erros.
  • Mantenha as mensagens para o usuário separadas dos diagnósticos para o desenvolvedor.
  • Escreva testes para os caminhos de falha, não apenas para o “happy path”.

Erros comuns

  • “Engolir” erros com um bloco catch vazio.
  • Lançar strings e perder o stack trace.
  • Capturar um erro e retornar um valor padrão que esconde um bug real.
  • Esquecer de tratar promises rejeitadas.
  • Exibir mensagens de erro brutas para os usuários.
  • Usar exceções para fluxo de controle comum.
  • Assumir que try/catch ao redor de um executor de promise captura erros assíncronos — isso não acontece.

Próximos passos

Os erros são onde o código assíncrono e a Fetch API encontram a realidade. Combine os padrões apresentados aqui com o DOM para renderizar estados amigáveis ao usuário, e revise os fundamentos de JavaScript sempre que um TypeError lembrar você que undefined não é uma função.

Lançando erros

Sempre lance objetos Error. Eles carregam um stack trace e uma mensagem; strings não carregam nenhum dos dois.

Prefira
if (!user) {
  throw new Error("User not found");
}
Evite
if (!user) {
  throw "User not found";
}

Esperado vs excepcional

Valide condições esperadas; reserve o try/catch para coisas que você não pode prever.

Prefira
if (!response.ok) {
  throw new Error(`HTTP ${response.status}`);
}
Evite
try {
  JSON.parse(input);
} catch {
  // swallowing every error hides bugs
}

Perguntas frequentes

Perguntas frequentes

Keep learning

Related topics from the roadmap.

$ comecar a aprender

Pronto para aprender Error Handling?

Nosso tutorial interativo te guia por Error Handling passo a passo — com quizzes e codigo real que voce pode executar no navegador.