Home/Blog/JavaScript

// JavaScript

TypeError: Cannot read properties of undefined, and the fix

Every example on this page was run on 12 October 2026 in JavaScript ES2023, and the output under each one is what it printed. How we test these posts.

TypeError: Cannot read properties of undefined (reading 'city') means you wrote something.city, or something[0], and something was undefined, so there was nothing to read the property from. The bug is the value to the left of the property, not the property itself. The most common fix is to find out why that value is missing; when it may legitimately be missing, read it with optional chaining, something?.city.

What does Cannot read properties of undefined mean?

Cannot read properties of undefined means JavaScript tried to read a property through a value that is undefined. Here user exists, but it has no address:

const user = { name: "Ava" };
console.log(user.address.city);

Output

TypeError: cannot read property 'city' of undefined
    at <eval> (main.js:2:25)

The JavaScript engine on this page words the message in an older style. Chrome, Edge and Node 22 print the same error as:

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

It is the same error, with the same causes and the same fixes. The at line gives the line and column, here line 2. user.address is undefined, and reading .city from it fails, so the message names city while the missing piece is address.

Why is the value undefined?

The undefined behind Cannot read properties of undefined comes from one of five places, and the first is by far the most common.

1. A property the object does not have

Reading a missing property does not fail on its own. It gives you undefined, and the error comes one step later, when you read through it. That is the case above, and it is the usual one with data from an API or a config file whose shape is not what you expected.

2. An array index past the end, or a search that found nothing

items[5] on a two-item array is undefined, and so is the result of find() when no element matches:

const users = [{ id: 1, name: "Ava" }, { id: 2, name: "Liam" }];
const match = users.find(u => u.id === 3);
console.log(match.name);

Output

TypeError: cannot read property 'name' of undefined
    at <eval> (main.js:3:18)

Off-by-one loops cause the index version: i <= items.length reads one element too many.

3. A function that does not return on every path

A function that ends without return gives back undefined. An arrow function with braces needs return too: x => { x * 2 } returns undefined, while x => x * 2 returns the number.

function getConfig(env) {
  if (env === "prod") {
    return { url: "https://example.com" };
  }
}

const config = getConfig("dev");
console.log(config.url);

Output

TypeError: cannot read property 'url' of undefined
    at <eval> (main.js:8:19)

4. A method that lost its this

Passing obj.method somewhere as a callback calls it without obj. Inside a class, this is then undefined, and the first this.something fails:

class Counter {
  constructor() {
    this.count = 0;
  }
  increment() {
    this.count += 1;
  }
}

const counter = new Counter();
const inc = counter.increment;
inc();

Output

TypeError: cannot read property 'count' of undefined
    at increment (main.js:6:9)
    at <eval> (main.js:12:4)

The same thing happens with setTimeout(counter.increment, 100), button.addEventListener("click", counter.increment) and array.forEach(obj.method).

5. Data that has not arrived yet

In the browser, a component often renders before its fetch finishes and reads data.items while data is still undefined. Destructuring a missing argument is the same mistake in another form, and Node 22 words it as Cannot destructure property 'name' of 'undefined' as it is undefined. The fixes below apply the same way.

Why do I get Cannot read properties of null?

Cannot read properties of null is the same error with null in place of undefined: something gave you an explicit “nothing”. In the browser it nearly always comes from a DOM lookup. document.querySelector("#save") and document.getElementById("save") return null when no element matches, so the next line fails with Cannot read properties of null (reading 'addEventListener'), or 'style', 'value' or 'classList'.

Two things cause it. The selector is wrong, or the script ran before the browser had parsed that element. Load the script with <script defer>, or at the end of <body>, so the page is parsed first. Our page has no DOM, but match() returns null the same way when nothing matches:

const found = "order shipped".match(/\d+/);
console.log(found.length);

Output

TypeError: cannot read property 'length' of null
    at <eval> (main.js:2:18)

How do I fix Cannot read properties of undefined?

Fix Cannot read properties of undefined at the place the value went missing; the fix depends on which cause it was.

Use optional chaining when the value may legitimately be missing. ?. stops and gives undefined instead of throwing, for null as well as undefined, and ?? supplies a default:

const user = { name: "Ava" };
console.log(user.address?.city);
console.log(user.address?.city ?? "no city");

const users = [{ id: 1, name: "Ava" }];
console.log(users.find(u => u.id === 3)?.name ?? "not found");
console.log("order shipped".match(/\d+/)?.[0] ?? "no number");

Output

undefined
no city
not found
no number

Do not scatter ?. everywhere, though. If address must always be there, a silent undefined only moves the bug somewhere harder to find.

Return something on every path, or fail early with a message that names the real problem:

function getConfig(env) {
  if (env === "prod") {
    return { url: "https://example.com" };
  }
  if (env === "dev") {
    return { url: "http://localhost:3000" };
  }
  throw new Error("unknown environment: " + env);
}

console.log(getConfig("dev").url);
console.log(getConfig("prod").url);

Output

http://localhost:3000
https://example.com

An error thrown in getConfig points at the cause. A TypeError three functions later points at a symptom.

Bind the method, or wrap it in an arrow function, so it keeps its object:

class Counter {
  constructor() {
    this.count = 0;
  }
  increment() {
    this.count += 1;
  }
}

const counter = new Counter();
const inc = counter.increment.bind(counter);
inc();
const inc2 = () => counter.increment();
inc2();
console.log(counter.count);

Output

2

Check array bounds in the loop condition. Use i < items.length, not <=, or loop with for (const item of items) so there is no index to get wrong.

How do I find which value is undefined?

Find the undefined value by looking just left of the property the message names. In a long chain such as order.customer.address.city, the message says which property it was trying to read, so the value before it is the missing one. If you cannot tell which link that is, log each step:

const order = { customer: { name: "Ava" } };
console.log(order.customer);
console.log(order.customer.address);

Output

{"name":"Ava"}
undefined

Node prints the object as { name: 'Ava' }, which is the same value. Then follow the undefined back to where it was set. It will be one of the causes above.

Can TypeScript catch it before the code runs?

TypeScript catches most of these before the code runs once "strict": true is set in tsconfig.json. It knows find() can return undefined, it flags a function that does not return on every path when its return type says it must, and it refuses user.address.city when address is optional. Turn on noUncheckedIndexedAccess as well and items[5] is typed as possibly undefined too.

In plain JavaScript, add // @ts-check at the top of the file and "strict": true under compilerOptions in a jsconfig.json. An editor that runs the TypeScript checker, such as VS Code, then shows the same errors.

MDN’s page on this family of TypeError messages lists them, and its pages on optional chaining and querySelector cover the two fixes above.

Cannot read properties of undefined (reading 'map') is this error on an array that has not loaded yet, most often in React, and (reading 'length') is the same on a missing array or string. Python’s version of a missing value is TypeError: ‘NoneType’ object is not subscriptable, with the same habit behind it: a function that returns nothing on one path.