Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
Erro resolvidoIniciantecódigo testado

Cannot read properties of undefined: como resolver

As quatro causas reais desse erro, cada uma reproduzida no Node com stack trace e a correção ao lado — array vazio, API, ordem assíncrona e typo.

Rodolfo Mori7 min de leitura

A mensagem completa é assim:

TypeError: Cannot read properties of undefined (reading 'total')

Ela quer dizer uma coisa só: você usou ponto (ou colchete) em cima de um valor que é undefined. O JavaScript não tem o que buscar dentro do nada, então interrompe ali.

O que a mensagem já entrega, e quase ninguém aproveita: o nome entre parênteses é a propriedade que você tentou ler. Ou seja, o undefined é exatamente o que está imediatamente antes do ponto. Em pedido.cliente.endereco.cidade, um erro (reading 'cidade') significa que endereco é undefinedpedido e cliente estão vivos.

Todo o código abaixo foi executado no Node 24.16.0 e as saídas são reais.

Leia a expressão como um endereço completo

Pense em pedido.cliente.endereco.cidade como um endereço escrito em etapas: prédio, andar, apartamento, cômodo. Para chegar à cidade, o JavaScript precisa encontrar cada parte anterior. Se endereco não existe, não há como abrir a porta seguinte chamada cidade.

O termo técnico é acesso a propriedade. O erro não afirma que a propriedade final está vazia; afirma que o valor antes dela é undefined ou null e, por isso, não pode ser consultado. Faça o diagnóstico sem adivinhar: copie a expressão que falhou, remova a última propriedade e imprima o resultado. Repita até encontrar o primeiro trecho ausente. Esse movimento de voltar uma porta é mais confiável que espalhar ?. pelo caminho, porque mostra quem deveria ter construído o dado.

O código mínimo que reproduz

js
const pedidos = [];
const ultimo = pedidos[0];

console.log('total do último pedido:', ultimo.total);
file:///private/tmp/loja/relatorio.mjs:4 console.log('total do último pedido:', ultimo.total); ^ TypeError: Cannot read properties of undefined (reading 'total') at file:///private/tmp/loja/relatorio.mjs:4:47 Node.js v24.16.0

Duas linhas úteis nessa saída: o arquivo com linha e coluna (relatorio.mjs:4:47) e o cursor ^ apontando o ponto exato. Comece por ali, sempre.

Causa 1 — o array está vazio

É a causa mais comum e a mais silenciosa: em desenvolvimento a lista tem itens, em produção ela chega vazia num dia atípico.

Quebrado:

js
const pedidos = [];
const ultimo = pedidos[0];

console.log('total do último pedido:', ultimo.total);

pedidos[0] num array vazio não lança erro — devolve undefined. O erro só estoura na linha seguinte, uma linha depois da causa.

Corrigido:

js
const pedidos = [];
const ultimo = pedidos[0];

console.log('total do último pedido:', ultimo?.total ?? 0);

if (pedidos.length === 0) {
  console.log('nenhum pedido para exibir');
}
total do último pedido: 0 nenhum pedido para exibir

Note que a correção tem duas partes. ?. impede a exceção; o if é o que efetivamente resolve o problema de produto — mostrar um estado vazio de verdade em vez de um zero mentiroso.

Causa 2 — a API respondeu, mas sem o campo

O fetch não lança erro quando a resposta é 404 ou 500. Ele resolve normalmente, e você segue lendo um corpo que não tem a forma esperada.

Os dois trechos abaixo rodaram contra o mesmo servidor de mentira, subido no topo do arquivo — é ele que responde 404 na porta 4310, e é por isso que o stack trace aponta uma linha mais adiante do que o trecho mostrado:

js
import { createServer } from 'node:http';

const servidor = createServer((req, res) => {
  res.writeHead(404, { 'content-type': 'application/json' });
  res.end(JSON.stringify({ erro: 'cliente não encontrado' }));
});

await new Promise((pronto) => servidor.listen(4310, pronto));

Quebrado:

js
const resposta = await fetch('http://localhost:4310/clientes/99');
const cliente = await resposta.json();

console.log('status:', resposta.status);
console.log('corpo:', cliente);
console.log('cidade:', cliente.endereco.cidade);
status: 404 corpo: { erro: 'cliente não encontrado' } TypeError: Cannot read properties of undefined (reading 'cidade') at file:///private/tmp/loja/api.mjs:19:41 Node.js v24.16.0

O log do corpo já denuncia tudo: veio { erro: ... }, e nesse objeto não existe endereco.

Corrigido:

js
const resposta = await fetch('http://localhost:4310/clientes/99');

if (!resposta.ok) {
  console.log(`API respondeu ${resposta.status} — nada a renderizar`);
} else {
  const cliente = await resposta.json();
  console.log('cidade:', cliente.endereco?.cidade ?? 'não informada');
}
API respondeu 404 — nada a renderizar

Causa 3 — a ordem de execução assíncrona

O valor vai existir. Só que ainda não existia quando você o leu. Esta é a causa que mais confunde, porque o código parece estar na ordem certa de cima para baixo — e está. O que não é sequencial é o momento em que o dado chega. Se await, callback e Promise ainda são território nebuloso, vale ler a lição sobre funções antes de seguir: aqui o problema é quando a função roda, não o que ela faz.

Quebrado:

js
let cliente;

function carregarCliente() {
  setTimeout(() => {
    cliente = { nome: 'Ana Souza', endereco: { cidade: 'Sorocaba' } };
  }, 100);
}

carregarCliente();
console.log('cidade:', cliente.endereco.cidade);
file:///private/tmp/loja/e05.mjs:10 console.log('cidade:', cliente.endereco.cidade); ^ TypeError: Cannot read properties of undefined (reading 'endereco') at file:///private/tmp/loja/e05.mjs:10:32 Node.js v24.16.0

carregarCliente() retornou imediatamente; o setTimeout só roda depois que a pilha esvazia. O console.log chegou antes.

Corrigido — a função devolve uma Promise, e quem chama espera:

js
function carregarCliente() {
  return new Promise((resolve) => {
    setTimeout(() => resolve({ nome: 'Ana Souza', endereco: { cidade: 'Sorocaba' } }), 100);
  });
}

const cliente = await carregarCliente();
console.log('cidade:', cliente.endereco.cidade);
cidade: Sorocaba

O sinal desta causa é característico: o dado aparece na tela um instante depois, ou aparece quando você adiciona um console.log antes (porque isso muda o tempo). Se o bug some ao observá-lo, é aqui.

Causa 4 — typo em propriedade aninhada

A causa mais boba e a mais difícil de enxergar: o objeto está certo, o caminho é que está errado por uma letra. Vale lembrar que const não congela o conteúdo de um objeto — o objeto pode ter sido alterado em outro ponto do código, e a propriedade que você procura simplesmente não é mais a que você espera.

Quebrado:

js
const pedido = {
  id: 1042,
  cliente: {
    nome: 'Ana Souza',
    enderecoEntrega: { cidade: 'Sorocaba', uf: 'SP' },
  },
};

console.log(pedido.cliente.endereco.cidade);
file:///private/tmp/loja/e07.mjs:9 console.log(pedido.cliente.endereco.cidade); ^ TypeError: Cannot read properties of undefined (reading 'cidade') at file:///private/tmp/loja/e07.mjs:9:37 Node.js v24.16.0

O campo chama enderecoEntrega, não endereco. E note o cursor: ele aponta cidade, o que confirma a regra do começo — o undefined é endereco.

Corrigido — e, antes da correção, o diagnóstico:

js
console.log(Object.keys(pedido.cliente));
console.log(pedido.cliente.enderecoEntrega.cidade);
[ 'nome', 'enderecoEntrega' ] Sorocaba

Object.keys no objeto anterior ao ponto que falhou é o atalho mais rápido de depuração que existe para esta família de erro. Em dois segundos você vê o nome verdadeiro do campo.

Como evitar

Optional chaining (?.)

Interrompe a expressão e devolve undefined em vez de lançar erro, se o valor antes dele for null ou undefined.

js
const pedido = { id: 1042, cliente: { nome: 'Ana Souza' } };

console.log(pedido.cliente?.enderecoEntrega?.cidade);
console.log(pedido.cliente?.enderecoEntrega?.cidade ?? 'retirar na loja');
console.log(pedido.itens?.[0]?.nome ?? 'carrinho vazio');
console.log(pedido.calcularTotal?.() ?? 'sem cálculo disponível');
undefined retirar na loja carrinho vazio sem cálculo disponível

Funciona em três formas: propriedade (a?.b), índice (a?.[0]) e chamada de função (a?.()). Esta última é a saída limpa para o parente próximo deste erro, o x is not a function.

O ?. precisa estar em cada elo

Colocar um só, no começo, não protege o resto da cadeia:

js
const pedido = { id: 1042, cliente: { nome: 'Ana Souza' } };

console.log(pedido.cliente?.enderecoEntrega.cidade);
file:///private/tmp/loja/e11.mjs:3 console.log(pedido.cliente?.enderecoEntrega.cidade); ^ TypeError: Cannot read properties of undefined (reading 'cidade') at file:///private/tmp/loja/e11.mjs:3:44 Node.js v24.16.0

cliente existe, então a cadeia não curto-circuita; enderecoEntrega é undefined e o .cidade seguinte quebra do mesmo jeito. O ?. protege apenas o elo em que ele está escrito.

Nullish coalescing (??) e não ||

?? só entra em ação para null e undefined. || entra para qualquer valor falso — e 0 e string vazia são valores legítimos:

js
const pedido = { desconto: 0, observacao: '' };

console.log(pedido.desconto || 'sem desconto');
console.log(pedido.desconto ?? 'sem desconto');
console.log(pedido.observacao || 'sem observação');
console.log(pedido.observacao ?? 'sem observação');
sem desconto 0 sem observação

A primeira linha é um bug clássico de e-commerce: desconto zero virou texto. Com ??, o zero sobrevive — e a quarta linha da saída está em branco de propósito, porque a string vazia também sobreviveu.

Roteiro de diagnóstico em quatro passos

  1. Leia o nome entre parênteses. O undefined é o que está imediatamente antes dele na expressão.
  2. Vá até o arquivo, linha e coluna do stack trace. O cursor ^ marca a coluna.
  3. Imprima o objeto anterior ao ponto que falhou, com Object.keys().
  4. Pergunte quem produziu esse valor: array vazio, resposta de rede, ou código que ainda não terminou de rodar? A resposta decide a correção.

Se o valor for null em vez de undefined, a mensagem muda mas o roteiro é o mesmo. E se o problema for o oposto — o objeto existe, mas o método não — a explicação está em funções em JavaScript. Para entender por que uma variável pode existir sem valor, variáveis em JavaScript cobre a zona morta temporal e o undefined do var.

Se esses dois assuntos ainda são novos, o guia de JavaScript mostra em que ordem estudar cada peça — este erro costuma aparecer justamente na fase em que se começa a consumir API e o dado deixa de ser escrito à mão. E se o trecho que quebrou veio de um assistente de IA, vale saber como um LLM produz código: ele escreve o caminho mais provável, não o caminho verificado — a suposição de que o campo sempre existe é exatamente o tipo de coisa que sai plausível e falsa.

  • typeerror
  • undefined
  • optional chaining
  • javascript
  • depuracao

Perguntas frequentes

Qual a diferença entre esse erro e o de null?
A mensagem muda para Cannot read properties of null. A causa é outra também — undefined normalmente é ausência acidental, e null é ausência declarada por alguém. Em navegador, querySelector devolve null quando não acha o elemento; ali o culpado costuma ser o script rodando cedo demais.
Optional chaining resolve todos os casos?
Não. Ele evita a exceção, mas não faz o dado aparecer. Se o valor deveria existir, esconder a falha com uma interrogação só empurra o bug para frente, onde ele fica mais caro de achar.
Por que o erro aponta uma linha que parece correta?
A linha está correta — o valor que chegou nela é que não é o esperado. A pergunta certa não é o que há de errado nesta linha, e sim quem produziu o valor que chegou aqui.
Como descobrir qual parte da expressão é undefined?
Leia o nome entre parênteses na mensagem. Cannot read properties of undefined (reading cidade) quer dizer que o que está imediatamente antes de .cidade é undefined — não o objeto do começo da expressão.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em Node 24.16.0, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. MDN — TypeError: cannot read property of undefined — developer.mozilla.org
  2. MDN — Optional chaining (?.) — developer.mozilla.org

Continue por aqui