Como ler uma stack trace Java e encontrar a causa do erro
Ler uma stack trace Java assusta no começo, porque, quando uma aplicação falha, ela costuma despejar dezenas ou centenas de linhas no console. Para quem está começando, aquele bloco de texto parece incompreensível, e a reação comum é copiar tudo e procurar na internet. Mas a stack trace é, na verdade, um mapa preciso do problema: ela diz qual erro aconteceu, em qual linha e qual caminho o programa percorreu até chegar lá. Saber lê-la é uma das habilidades que mais aceleram um desenvolvedor.
O que é uma stack trace
Quando um método chama outro, que chama outro, o Java empilha essas chamadas (a pilha de execução, ou call stack). Quando uma exceção não é tratada, o Java imprime essa pilha no momento do erro: do ponto exato onde a exceção ocorreu até o início da execução.
Anatomia de uma stack trace Java
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "nome" is null
at br.com.loja.Cliente.validarNome(Cliente.java:42)
at br.com.loja.ClienteService.cadastrar(ClienteService.java:18)
at br.com.loja.Main.main(Main.java:9)
Leia assim:
- Primeira linha: o tipo da exceção (
NullPointerException) e a mensagem. Nas versões modernas do Java, a mensagem já explica qual variável era nula. - Linhas com
at: cada uma é um método na pilha, com classe, método, arquivo e número da linha. - A primeira linha
até onde o erro aconteceu:Cliente.java, linha 42. - As linhas seguintes mostram quem chamou:
ClienteService.cadastrar, chamado porMain.main.
Neste caso, a pergunta certa é: por que nome chegou nulo ao método validarNome? A resposta provavelmente está em quem chamou, na linha 18 de ClienteService.
Encontre a primeira linha do seu código
Em aplicações reais, a pilha mistura o seu código com o de frameworks e bibliotecas (Spring, Hibernate, Tomcat). A regra prática: procure a primeira linha que pertence ao seu pacote (por exemplo, br.com.loja). As linhas de framework mostram por onde a requisição passou, mas a causa quase sempre está no seu código.
Caused by: a causa real está no fim
Exceções muitas vezes são "embrulhadas" em outras. A stack trace mostra a cadeia com Caused by:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clienteService'
...
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: ...
...
Caused by: java.lang.IllegalStateException: Propriedade app.jwt.secret não configurada
at br.com.loja.config.JwtConfig.<init>(JwtConfig.java:21)
Leia o último Caused by. Ele é a causa raiz. No exemplo, a aplicação não subiu porque faltava uma variável de configuração; veja variáveis de ambiente e segredos.
A expressão ... 25 more indica que as linhas restantes são iguais às da exceção acima e foram omitidas.
Exceções mais comuns e o que costumam significar
| Exceção | Significado | Onde olhar |
|---|---|---|
| NullPointerException | Uso de uma referência nula | De onde veio o valor nulo |
| ArrayIndexOutOfBoundsException | Índice fora do tamanho do array | Laços e cálculos de índice |
| ClassCastException | Conversão de tipo inválida | Casts e coleções sem tipo genérico |
| NumberFormatException | Texto que não é número | Entrada do usuário, arquivos, JSON |
| IllegalArgumentException | Argumento inválido para o método | Validações e parâmetros |
| ConcurrentModificationException | Lista alterada enquanto era percorrida | Remoções dentro de um for |
| OutOfMemoryError | A JVM ficou sem memória | Carregamento de dados em excesso, vazamentos |
| StackOverflowError | Recursão infinita ou muito profunda | Métodos que chamam a si mesmos, toString e equals recursivos |
Erros comuns no Spring Boot
Port 8080 was already in use: outra aplicação já usa a porta. Encerre o processo ou mudeserver.port.Failed to configure a DataSource: falta a configuração do banco de dados, ou a dependência do banco foi incluída sem ser usada.No qualifying bean of type: o Spring não encontrou uma classe para injetar. Verifique anotações como@Servicee@Repositorye se a classe está em um pacote abaixo da classe principal.LazyInitializationException: acesso a uma relação do JPA depois que a sessão foi fechada, geralmente ao montar a resposta da API. Use DTOs e busque os dados necessários na consulta.HttpMessageNotReadableException: o JSON enviado está malformado ou não corresponde ao objeto esperado. Veja JSON para iniciantes.
Para montar a base de uma API, veja sua primeira API com Spring Boot.
Um roteiro para depurar
- Leia a mensagem com atenção. Muitas vezes ela já diz o problema.
- Ache o último Caused by.
- Ache a primeira linha do seu código naquela exceção.
- Abra o arquivo na linha indicada e pergunte: quais valores poderiam causar esse erro aqui?
- Reproduza o erro com o menor caso possível.
- Use o depurador da IDE: coloque um breakpoint na linha, rode em modo debug e inspecione as variáveis. É muito mais eficiente que espalhar
System.out.println. - Corrija e escreva um teste que reproduz o problema, para que ele não volte. Veja testes automatizados com JUnit.
Stack traces em produção
Em produção, as stack traces devem ir para os logs, nunca para a resposta da API, porque revelam detalhes internos que ajudam atacantes. Registre a exceção completa no log e devolva ao cliente uma mensagem genérica com um identificador da requisição. Veja logs em produção e códigos de status HTTP.
Pedindo ajuda do jeito certo
Ao perguntar a um colega, em um fórum ou a uma ferramenta de IA, envie a stack trace completa (como texto, não print), o trecho de código das linhas citadas e o que você já tentou. Remova senhas, tokens e dados pessoais antes de colar qualquer coisa. Uma boa pergunta costuma render uma resposta em minutos.
Sistemas sob medida
A PruPru desenvolve APIs, sistemas web e integrações com as mesmas práticas descritas neste guia. Se a sua empresa precisa de software bem construído, conheça os serviços.
Ver serviços →Perguntas frequentes
Qual linha da stack trace devo olhar primeiro?
Leia a mensagem da exceção, procure o último Caused by, que é a causa raiz, e nele encontre a primeira linha que pertence ao seu próprio código. É ali que costuma estar o problema.
O que significa "... 25 more" no fim da stack trace?
Que as linhas restantes são idênticas às da exceção que aparece acima na cadeia e foram omitidas para não repetir informação.
Como evitar NullPointerException?
Valide entradas, inicialize coleções vazias em vez de nulas, use Optional para valores que podem não existir e preste atenção às mensagens das versões modernas do Java, que indicam exatamente qual variável era nula.
Devo mostrar a stack trace para o usuário da API?
Não. Ela revela detalhes internos da aplicação. Registre a stack trace completa nos logs e devolva ao cliente uma mensagem genérica com um identificador para consulta.