Cannot read properties of undefined: como encontrar e corrigir a origem do erro JavaScript
Publicado em 2026-08-29T20:13:00Z · atualizado em 2026-08-29T19:13:54+00:00
O erro **TypeError: Cannot read properties of undefined (reading 'x')** aparece quando o JavaScript tenta acessar uma propriedade em um valor que é `undefined`. A propriedade mencionada não é necessariamente a origem: em `pedido.cliente.nom
Cannot read properties of undefined: como encontrar e corrigir a origem do erro JavaScript
O erro TypeError: Cannot read properties of undefined (reading 'x') aparece quando o JavaScript tenta acessar uma propriedade em um valor que é undefined. A propriedade mencionada não é necessariamente a origem: em pedido.cliente.nome, o problema pode ser pedido ou cliente. Adicionar ?. em toda parte evita a exceção, mas pode transformar um dado obrigatório ausente em silêncio.
Este guia mostra como localizar o primeiro valor inválido, reproduzir a falha, interpretar a pilha, validar contratos de API, corrigir arrays, DOM e tarefas assíncronas e decidir quando usar optional chaining, valor padrão ou erro explícito.
Legenda: a propriedade citada é o acesso que falhou; o diagnóstico procura o objeto imediatamente à esquerda.
O que a mensagem realmente diz
const pedido = { cliente: undefined };
console.log(pedido.cliente.nome);
O motor tenta ler nome de undefined. A MDN explica que null e undefined não possuem propriedades. Navegadores podem escrever mensagens diferentes, mas o tipo é TypeError.
Separe a cadeia:
console.log({ pedido });
console.log({ cliente: pedido?.cliente });
Não registre objeto inteiro em produção se ele contém dados pessoais ou tokens. Prefira identificadores anonimizados e a presença dos campos.
Reproduza com a menor entrada possível
Crie erro.js:
function nomeDoCliente(pedido) {
return pedido.cliente.nome;
}
console.log(nomeDoCliente({ cliente: { nome: "Ada" } }));
console.log(nomeDoCliente({}));
Execute node erro.js. A primeira chamada funciona; a segunda prova que a função aceita uma entrada que não satisfaz o contrato. A correção depende da regra: cliente é obrigatório ou opcional?
Teste pelo menos entrada válida, campo ausente, null, tipo incorreto e objeto vazio. Um caso mínimo remove framework e rede do diagnóstico.
Leia a stack trace do seu código para fora
A pilha mostra arquivo, linha e funções chamadas. Comece na primeira linha que pertence ao seu código, não na biblioteca interna. Em código empacotado, habilite source maps somente conforme a política do ambiente e mantenha-os protegidos quando revelarem fonte privada.
function formatar(pedido) { return pedido.cliente.nome.toUpperCase(); }
function renderizar(dados) { return formatar(dados); }
renderizar({});
Coloque um breakpoint antes da linha, inspecione pedido e avance uma expressão por vez. Não altere várias condições enquanto tenta reproduzir.
undefined, null e propriedade inexistente
Uma variável declarada sem valor recebe undefined. Ler uma propriedade ausente também devolve undefined. null costuma representar ausência intencional. Ambos falham ao receber novo acesso:
const a = {};
console.log(a.cliente); // undefined
console.log(a.cliente.nome); // TypeError
Use verificações explícitas quando a distinção importa:
if (!("cliente" in a)) throw new Error("campo cliente ausente");
if (a.cliente === null) return "cliente removido";
Não use typeof valor === "object" sozinho: typeof null é "object" por compatibilidade histórica.
Optional chaining não é correção universal
const cidade = cliente?.endereco?.cidade;
O operador ?. interrompe uma cadeia contínua quando encontra null ou undefined, retornando undefined. A documentação da MDN alerta que agrupar quebra essa continuidade:
const cidade = (cliente?.endereco).cidade; // ainda pode falhar
Use optional chaining quando ausência é válida, como um segundo telefone opcional. Para id obrigatório de pagamento ou resultado essencial de autenticação, lance erro claro na fronteira. Silenciar pode produzir cálculo ou interface incorretos.
Valor padrão: prefira ?? quando zero é válido
const tentativas = config.tentativas ?? 3;
?? usa o padrão apenas para null ou undefined. || também troca 0, false e string vazia:
const descontoErrado = produto.desconto || 10; // transforma 0 em 10
const desconto = produto.desconto ?? 10;
O padrão precisa ser semanticamente seguro. Inventar lista vazia pode esconder que uma API falhou. Se a tela não pode funcionar sem dados, mostre estado de erro.
Legenda: a regra do campo determina o tratamento; a sintaxe vem depois.
Arrays: índice inexistente e find sem resultado
const itens = [];
console.log(itens[0].nome);
itens[0] é undefined. Verifique comprimento ou use optional chaining se “nenhum item” é permitido:
const primeiroNome = itens[0]?.nome ?? "Sem itens";
find também pode retornar undefined:
const item = itens.find(x => x.id === procurado);
if (!item) throw new Error(`Item ${procurado} não encontrado`);
return item.nome;
Não confunda find com filter: o primeiro devolve um elemento ou undefined; o segundo sempre devolve array.
Desestruturação exige uma origem válida
function exibir({ nome }) {
return nome;
}
exibir(); // falha antes do corpo
Se o argumento inteiro é opcional:
function exibir({ nome = "Sem nome" } = {}) {
return nome;
}
Se ele é obrigatório, validar explicitamente produz mensagem melhor:
function exibir(dados) {
if (!dados) throw new TypeError("dados são obrigatórios");
const { nome } = dados;
return nome;
}
API: valide na fronteira, não na última tela
HTTP 200 não garante o formato esperado. A API pode devolver { data: [...] } enquanto o código espera { items: [...] }.
async function carregarPedidos() {
const resposta = await fetch("/api/pedidos");
if (!resposta.ok) throw new Error(`HTTP ${resposta.status}`);
const json = await resposta.json();
if (!json || !Array.isArray(json.items)) {
throw new TypeError("Resposta inválida: items deve ser array");
}
return json.items;
}
Valide tipos, campos obrigatórios e versões logo após receber dados externos. Bibliotecas de schema ajudam, mas uma validação manual pequena já melhora a mensagem. Não inclua o corpo completo em logs quando houver dados sensíveis.
Fluxo assíncrono e estado ainda não carregado
let usuario;
carregarUsuario().then(valor => { usuario = valor; });
console.log(usuario.nome);
A leitura acontece antes da Promise resolver. Aguarde:
const usuario = await carregarUsuario();
console.log(usuario.nome);
Em interfaces, represente estados separados: carregando, sucesso vazio, sucesso com dados e erro. Um objeto undefined não deveria representar todos eles.
Também proteja contra respostas fora de ordem. Uma busca antiga pode terminar depois da nova e sobrescrever estado. Use AbortController, identificador de requisição ou mecanismo do framework.
DOM: o elemento pode não existir ainda
document.querySelector("#salvar").addEventListener("click", salvar);
querySelector retorna null quando não encontra. Coloque o script depois do HTML, use defer ou espere DOMContentLoaded. Para elemento obrigatório:
const botao = document.querySelector("#salvar");
if (!botao) throw new Error("Elemento #salvar não encontrado");
botao.addEventListener("click", salvar);
botao?.addEventListener é adequado somente quando o componente é realmente opcional naquela página.
this perdido em callbacks
class Carrinho {
constructor() { this.itens = []; }
total() { return this.itens.length; }
}
const carrinho = new Carrinho();
const total = carrinho.total;
total();
O método perdeu o receptor. Corrija com bind, função de seta no chamador ou método definido conforme o desenho:
const totalSeguro = carrinho.total.bind(carrinho);
console.log(totalSeguro());
Não transforme todos os métodos em setas sem entender custo e herança. A origem é a forma de chamada.
TypeScript e checagem estática
Com strictNullChecks, tipos obrigam tratamento de ausência antes da execução:
type Cliente = { nome: string; endereco?: { cidade?: string } };
function cidade(cliente: Cliente): string {
return cliente.endereco?.cidade ?? "Não informada";
}
TypeScript não valida JSON em tempo de execução. Dados externos continuam precisando de schema ou guardas. Evite as Cliente apenas para calar o compilador; isso afirma algo sem verificar.
Observabilidade sem expor dados
Registre contexto estrutural:
console.error("pedido inválido", {
possuiPedido: pedido != null,
possuiCliente: pedido?.cliente != null,
requestId
});
Inclua versão da aplicação, rota e identificador de correlação. Não registre nomes, e-mails, tokens ou objetos integrais. Em produção, agrupe erros pela linha original via source map protegido e preserve a primeira ocorrência.
Testes que impedem a volta do erro
import assert from "node:assert/strict";
function nomeDoCliente(pedido) {
if (!pedido?.cliente?.nome) throw new TypeError("nome do cliente ausente");
return pedido.cliente.nome;
}
assert.equal(nomeDoCliente({ cliente: { nome: "Ada" } }), "Ada");
assert.throws(() => nomeDoCliente({}), /nome do cliente ausente/);
Teste a menor entrada que reproduziu o incidente e o comportamento esperado. Se ausência é aceita, confirme o valor padrão. Se é erro, confirme a mensagem e o estado apresentado ao usuário.
Use o criador de fluxogramas para mapear carregamento e estados, as ferramentas para organizar testes e a biblioteca para aprofundar JavaScript e programação.
Uma correção robusta também precisa preservar o contrato entre camadas. Se a API alterou cliente para customer, adicionar pedido.cliente?.nome apenas esvazia a tela. Compare uma resposta válida conhecida com a atual, verifique versão e mantenha teste de contrato no consumidor. Mudanças incompatíveis devem ser versionadas ou coordenadas.
Ao normalizar dados, faça isso uma vez:
function normalizarPedido(raw) {
if (!raw || typeof raw !== "object") {
throw new TypeError("pedido deve ser objeto");
}
const cliente = raw.cliente;
if (!cliente || typeof cliente.nome !== "string" || !cliente.nome.trim()) {
throw new TypeError("cliente.nome deve ser texto não vazio");
}
return {
id: String(raw.id),
cliente: { nome: cliente.nome.trim() },
observacao: raw.observacao ?? null
};
}
Depois dessa fronteira, o restante da aplicação pode trabalhar com formato confiável. Não repita ?. em cada componente para compensar dados brutos indefinidos.
Em listas renderizadas, confira também transformações intermediárias. map preserva o tamanho, mas uma função sem return gera undefined:
const nomesErrados = pedidos.map(p => { p.cliente.nome; });
const nomes = pedidos.map(p => p.cliente.nome);
Chaves e mapas apresentam outro caso:
const porId = new Map(pedidos.map(p => [p.id, p]));
const pedido = porId.get(id); // pode ser undefined
Valide o resultado de get antes da propriedade. Isso vale para caches, seletores e dicionários.
Condições de corrida exigem teste controlado. Simule uma resposta lenta e outra rápida, mude filtros antes da primeira terminar e confirme que a antiga não substitui o estado. Um AbortController pode cancelar a solicitação anterior:
let controller;
async function pesquisar(termo) {
controller?.abort();
controller = new AbortController();
const res = await fetch(`/api/busca?q=${encodeURIComponent(termo)}`, {
signal: controller.signal
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
Trate AbortError como cancelamento esperado, não como dado undefined. Mantenha o erro real visível.
Em componentes, não derive estado copiando dados incompletos se ele pode ser calculado da fonte. Cada cópia aumenta a chance de ficar desatualizada. Defina valores iniciais compatíveis com o tipo: lista começa como [] quando vazio é um estado válido; objeto obrigatório pode começar como estado loading, não como {} fingindo estar completo.
Por fim, reveja toda ocorrência de ?. adicionada durante o conserto. Para cada uma, responda: ausência é permitida? qual interface o usuário verá? existe métrica? Se não há resposta, a sintaxe provavelmente está escondendo um contrato quebrado.
Checklist final
Antes de concluir, procure variações da mesma falha. Se cliente.nome ficou indefinido, campos vizinhos podem depender do mesmo contrato antigo. Uma busca direcionada pela propriedade e pelo tipo da resposta encontra consumidores que ainda não passaram pela normalização.
Revise também caminhos de erro. Interfaces frequentemente validam o sucesso, mas tentam ler erro.response.data.message quando response não existe em uma falha de rede. Extraia mensagem de modo defensivo e preserve a causa:
function mensagemDoErro(erro) {
if (erro instanceof Error && erro.message) return erro.message;
return "Falha inesperada";
}
Não apresente detalhes internos ao usuário. Mostre uma orientação segura e envie contexto técnico redigido ao monitoramento.
Em testes de interface, cubra carregamento lento, resposta vazia, erro HTTP, JSON inválido e navegação antes da conclusão. Esses estados reproduzem muitos undefined que não aparecem no caminho feliz.
Uma correção está completa quando o contrato inválido é detectado na fronteira, a interface apresenta estado coerente e o monitoramento registra a categoria sem dados sensíveis. Apenas deixar de lançar a exceção não garante comportamento correto.
Faça ainda uma revisão do valor inicial de cada estado compartilhado. Contextos, stores e propriedades de componentes devem publicar um tipo previsível desde a primeira renderização. Se a inicialização é assíncrona, exponha explicitamente status: "loading" e data: null, em vez de um objeto parcialmente preenchido. Consumidores passam a tratar a fase, e não a adivinhar se determinada propriedade já apareceu.
Ao corrigir biblioteca ou função reutilizada, documente se ela retorna undefined, null, array vazio ou lança exceção. Consistência reduz verificações contraditórias e torna o próximo erro mais fácil de localizar.
- a primeira linha do código da aplicação foi localizada;
- a cadeia foi dividida para encontrar o valor indefinido;
- a entrada mínima reproduz a falha;
- ausência obrigatória e opcional foram diferenciadas;
?.e??preservam a regra de negócio;- arrays,
find, desestruturação e DOM foram verificados; - respostas de API são validadas na fronteira;
- estados assíncronos são explícitos;
- TypeScript não substitui validação de runtime;
- logs não expõem dados sensíveis;
- um teste cobre a regressão.
Documentação primária
- MDN — null ou undefined sem propriedades
- MDN — optional chaining
- MDN — nullish coalescing
- MDN — Array.find
- MDN — Fetch API
Nota de produção
Rascunho autoral orientado à busca “Cannot read properties of undefined como corrigir”. Os exemplos usam JavaScript padrão e dados fictícios. A revisão humana deve executá-los em Node.js e navegador compatíveis, confirmar a política de logs e revisar a terminologia antes da publicação.
Camada extra: como tomar uma decisão melhor neste cenário
A parte mais importante de Cannot read properties of undefined: como encontrar e corrigir a origem do erro JavaScript não é decorar um botão: é entender quais sinais confirmam o diagnóstico e quais sinais indicam que estamos resolvendo o problema errado.
O erro **TypeError: Cannot read properties of undefined (reading 'x')** aparece quando o JavaScript tenta acessar uma propriedade em um valor que é `undefined`. A propriedade mencionada não é necessariamente a origem: em `pedido.cliente.nom A ideia central pode ser testada com quatro perguntas: o que foi observado, qual hipótese explica o sintoma, qual mudança é reversível e qual evidência prova que funcionou. Esse encadeamento evita que uma coincidência seja confundida com causa e torna o procedimento repetível por outra pessoa.
Qualidade de IA precisa de um teste, não de uma impressão
Para JavaScript, TypeError, undefined, debug, escolha três tarefas representativas: uma simples, uma ambígua e uma em que a resposta possa ser conferida em fonte primária. Compare utilidade, rastreabilidade, privacidade, velocidade e quantidade de correção humana necessária. Uma resposta elegante não compensa uma citação inexistente ou uma conclusão que não pode ser reproduzida.
Separe ainda o que pode sair do dispositivo do que deve permanecer local. Dados públicos toleram fluxos diferentes de documentos internos, contratos, informações pessoais ou bases de clientes. A escolha entre processamento local e nuvem deve ser feita pelo risco do conteúdo, não apenas pela conveniência da interface.
Grade de avaliação prática
| Critério | Pergunta | Evidência |
|---|---|---|
| Correção | A resposta bate com a fonte? | Checagem independente |
| Rastreabilidade | É possível localizar de onde veio? | Citação ou trecho verificável |
| Privacidade | Que dado sai do dispositivo? | Política e configuração |
| Esforço | Quanto trabalho humano resta? | Tempo de revisão |
O ponto em que a IA deixa de ajudar
Se a tarefa exige precisão absoluta e a saída não pode ser validada, a automação deve ser limitada a apoio: localizar trechos, organizar opções ou preparar uma primeira versão. A decisão final precisa permanecer com alguém capaz de verificar a fonte e assumir a responsabilidade pelo resultado.
Checklist de fechamento
- Registre o estado inicial antes de alterar qualquer coisa.
- Faça uma mudança por rodada e anote o efeito.
- Teste um caso normal, um caso-limite e o cenário que originalmente falhou.
- Confirme que a solução continua válida depois de reiniciar, reabrir ou repetir o fluxo.
- Guarde uma forma de voltar ao estado anterior quando a alteração for destrutiva.
Esse método acrescenta profundidade sem transformar o artigo em teoria abstrata: o leitor entende por que cada passo existe e como reconhecer quando a situação exige uma decisão diferente.
