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

Filed under Next.js & React errors

Most likely causeAbout 10 min · 6 steps

Your code read a property off a value that is still undefined — usually data that has not finished loading, or data in a different shape than the code expects.

Find the line and the word after 'reading'
Log the value just before the crash
Guard the render or fix the data shape

Fastest route

Give your AI this prompt

Copy it, replace the bracketed part with your error, and send it.

Preview the prompt
I am getting this error: TypeError: Cannot read properties of undefined (reading '[word from the error]').

The stack trace points to this file and line: [paste the first stack frame from your own code]. Here is the code around that line: [paste the component code]. Here is what the data actually looks like when I log it just before the crash: [paste the logged value, or say "it is undefined on first render, then real data"].

Please: 1) tell me which value is undefined and why — data not loaded yet, a shape mismatch, a failed fetch, or a prop that was never passed, 2) fix that root cause in the smallest way possible, 3) only use optional chaining for values that are genuinely allowed to be absent.

Constraints: do not add ?. to every line to silence the crash, do not rewrite the whole component, and tell me the cause before you change code.

Fix it yourself

Follow the repair

  1. Read the error backwards. In "Cannot read properties of undefined (reading 'map')", the property is map and something that should have been an array was undefined. Under the message, the stack trace lists files and line numbers — click the first one that is your own code. That line, not the whole page, is where the fix belongs.
  2. Check whether the data simply has not arrived yet. Put a log on the line before the crash and reload:
    console.log("value right before crash:", items);
    If it prints undefined first and real data a moment later, you have a timing problem, not a data problem — go to step 3. If it is undefined forever, skip to step 5.
  3. Guard the render while data is missing. Show a loading state until the value exists, and give list state a safe starting value so the first render has something harmless to read:
    const [items, setItems] = useState([]);   // [] not nothing
    
    if (loading) return <p>Loading…</p>;
    An empty array can be mapped, counted, and measured without crashing; undefined cannot.
  4. Use optional chaining where a missing value is acceptable. user?.profile?.name reads safely through missing levels and gives back undefined instead of throwing. Use it for genuinely optional values — a user who may not have set a profile yet. If you find yourself chaining every line of a component, the shape is wrong; fix that instead.
  5. Check the shape of what actually came back. Log the entire response once, exactly as it arrived, and compare it field by field with what the code expects. The usual traps: rows nested under data.data, an array where the code treats the value as a single object, and renamed fields — databases love created_at while AI-written code guesses createdAt. Adjust the code to the real shape, not the imagined one.
  6. In Next.js, check where the data was supposed to come from. If the value comes from a parent, confirm the parent actually passes that prop. If it comes from a server fetch, check the fetch did not fail and return nothing. And if it comes from the page URL, remember that in current Next.js versions params and searchParams arrive as promises — reading a property off them before awaiting gives you this same crash.
Why this happensOptional explanation

React renders your page first and fetches data second. When a component starts up, its state begins as whatever you initialised it with — very often nothing at all, which in JavaScript is undefined. The component happily tries to render using that nothing: it asks for user.name or items.map(...) before a user or any items exist, and JavaScript throws this error because you cannot read a property from a value that is not there.

The second big cause is shape mismatch. Your code was probably written — by you or by an AI builder — against an imagined version of the data: an object where the API actually returns an array, a field called title where the database calls it post_title, a response that wraps everything in an extra data layer. The value one level up exists; the thing you reached for inside it does not, so the read fails exactly the same way.

  • Data not loaded yet: first render runs before the fetch resolves; the classic crash-on-first-load.
  • Wrong shape: the response is an array, a nested object, or uses different field names than the code assumes.
  • A fetch that quietly failed: the error path returned nothing, so the component received undefined instead of data.
  • A prop nobody passed: the parent component never sent the value the child reaches for.

Quick answers

Why does it crash on first load but work after I refresh?

Because the first render happens before the data arrives. On first load the value is undefined and the page crashes; by the time you refresh, cached data or a faster response lets the same code squeak by. The bug is the missing loading guard, not the refresh.

Is optional chaining (?.) a real fix or just a bandage?

Both. If a value is legitimately optional — a profile may have no avatar — optional chaining is the correct tool. But if the value should always exist, ?. just hides the crash and shows empty UI instead, which makes the real shape bug harder to find. Fix the shape first; then chain where absence is genuinely fine.

The error names a property I never typed. Where does it come from?

Probably library or framework code that ran on your data — a .map, a formatter, a chart component. Ignore the frames you do not recognise and look for the first frame that names one of your own files; that line is where the undefined value came from.

One fix, every Friday.

One real error, explained in plain English, with the fix — in your inbox every Friday. No spam, no jargon, unsubscribe anytime.