Voltar
O erro em JavaScript pode estar mentindo para você

Seu erro em JavaScript pode estar escondendo informações importantes

Aprofundamento CEVIU

Aprofundamento

O ponto de partida do texto é um log com o campo err vazio ({}). O erro capturado tinha mensagem e uma cause encadeada, mas JSON.stringify só escreve propriedades próprias enumeráveis, e message e cause são não enumeráveis. Object.keys(err) também retorna [], enquanto Object.getOwnPropertyNames mostra que a informação continua no objeto. Já console.log(err) no Node.js imprime mensagem, stack e a cause aninhada, porque seu formatter procura por tudo isso.

O stack também não é tão confiável quanto parece. O ECMAScript define message, name e cause, mas não stack. No V8, o stack é capturado na criação do erro (não no throw), guarda por padrão só os 10 frames mais recentes (Error.stackTraceLimit) e pode ser alterado por Error.captureStackTrace e Error.prepareStackTrace. No Node.js, sem --enable-source-maps, as posições apontam para o JavaScript gerado. Frames async são reconstruídos pela cadeia de promises, e um callback de timer perde a origem. Também há o fato de que o valor capturado no catch nem sempre é um Error: por isso o TypeScript tipa a variável como unknown com useUnknownInCatchVariables, e o instanceof Error falha entre realms (Error.isError está disponível no Node.js 24.2.0).

Com o cause, o erro externo guarda o original, mas só quem percorre a cadeia recupera o contexto. O texto mostra que a cadeia pode ter ciclo (o Node.js marca [Circular *1], mas um loop ingênuo não), pode terminar em string ou número e pode ser muito longa. A travessia segura rastreia objetos visitados e impõe limite de profundidade. Com AggregateError, produzido por Promise.any, as falhas ficam em errors, também não enumerável.

Por que isso importa

Para quem opera backend em Node.js, isso significa que passar o erro direto como campo do logger pode gerar registros que parecem completos e não dizem nada no pós-incidente. A leitura editorial é que vale ter uma função única de serialização de erros, com limite de profundidade, detecção de ciclo e tratamento de aggregates, em vez de confiar no comportamento de cada logger.

Perguntas frequentes

Por que JSON.stringify de um Error retorna {}?

Porque JSON.stringify escreve apenas propriedades próprias enumeráveis. Em um Error, message e cause são criadas como não enumeráveis, então ficam de fora. Subclasses que atribuem campos no construtor expõem só esses campos, sem message nem cause.

O que o cause do Error faz?

Ao passar { cause } como segundo argumento do construtor, o erro novo guarda o original. Isso evita perder a falha de baixo nível quando uma camada faz wrap. A cause mantém o stack do local onde foi criada, e só quem percorre a cadeia recupera tudo.

Como percorrer a cadeia de causes com segurança?

Use um loop que registre os objetos já visitados e pare em um limite de profundidade. Assim, ciclos não travam o código e cadeias longas são cortadas. Causes que são string ou número entram como último elemento.

O stack trace é padronizado entre engines?

Não. O ECMAScript não define a propriedade stack. Formato, limite de frames e ferramentas como Error.captureStackTrace e Error.prepareStackTrace são do V8, e o Firefox lista outras propriedades, como fileName e lineNumber.

Fontes

Avalie este artigo:
Categoria
CEVIU Web Dev
Publicado
12 de novembro de 2026
Editoria
CEVIU Web Dev

Quer receber mais sobre CEVIU Web Dev?

Conteúdo curado diariamente, direto no seu e-mail.

Conteúdo curado diariamenteDiversas categoriasCancele quando quiser