What's the difference between undefined and null?
In one sentence:undefined means a variable, property, or argument was never given a value, while null means something was deliberately set to empty, and JavaScript throws a TypeError the moment your code tries to read a property or call a method on either one.
What it actually is
undefined is what JavaScript gives you automatically when nothing has been provided: a variable you declared but never assigned, a function argument nobody passed in, an object property that was never set. null is different. Someone chose it on purpose, to mark a spot that exists but is deliberately empty.
Picture a delivery slot on a schedule. A slot nobody has ever booked is undefined, empty because it was never touched. A slot someone booked and then explicitly canceled is null, empty on purpose.
JavaScript treats the two as loosely equal (null == undefined is true) but not strictly equal (null === undefined is false). One old quirk worth knowing: typeof null returns "object", not "null", a bug from JavaScript’s first version kept alive because fixing it would break old code that depends on it.
The error you’re pasting everywhere, Cannot read properties of undefined (reading 'map'), means your code tried to read a property or call a method (here, .map()) on a value that turned out to be undefined at that exact moment. JavaScript can’t look anything up on nothing, so it throws instead of guessing.
Why your AI just did this
The data hasn’t loaded yet. Say your agent fetches a list of posts and renders it with posts.map(post => ...). If posts starts out undefined while the fetch is still in flight, that line crashes on the first render, even though the fetch is seconds from succeeding. This is common wherever your agent uses async and await: the component renders once before the awaited data comes back, and once again after.
The property path is wrong. Your agent assumes an API response looks like response.data.posts, but the real shape is response.posts. Reading .data off the response gives undefined, and .posts on that is what throws. It’s a guess about JSON shape that turned out wrong, easy to make when the agent never saw the actual response, only your description of it.
The API’s shape changed. A Supabase query using .maybeSingle() returns null, not an error, when no rows match the filter, so code that assumed there would always be a row breaks the first time one is missing. A third-party endpoint wraps its data in a new object. Code your agent wrote against the old shape meets a response it never tested against.
When you’ll run into it
The exact wording depends on the browser reading it, so don’t expect a screenshot from a friend’s Firefox to match what you see in Chrome. For a broken posts.map(...) call, Chrome and other V8-based browsers show Cannot read properties of undefined (reading 'map'), naming the property you tried to read. Firefox shows something closer to posts is undefined, naming the variable itself instead of the property. Safari shows undefined is not an object (evaluating 'posts.map'), spelling out the whole expression.
You’ll first see it in your browser console as red text, and depending on your framework, it can take the whole page down to a blank screen instead of breaking just the one component. It tends to arrive in a frustrating order: the page works when you test it with real data, then breaks the moment someone hits an edge case, like a brand-new account with no posts yet, or a search with zero results.
What to check
- Read the word in parentheses in the Chrome message,
(reading 'map'). That names the property your code wanted; work backward from there to find which variable wasundefined. - Log the exact value right before the failing line, so you see its real shape instead of the one you assumed.
- Check whether your component renders before its data has arrived. A loading state, or a default value like an empty array, fixes the timing instead of just hiding the symptom.
- Confirm the API response actually looks the way your code reads it. Log the raw response and compare it to the property path your code follows.
- Use optional chaining (
data?.map(...)) as a safety net against crashes, not as a substitute for finding out why the data is missing. - If
nullis a real, expected outcome (no results found, for instance), handle that case on purpose instead of letting.map()hit it by accident.
Say it like a dev
Instead of: “the page just goes blank sometimes”
Say: “I’m getting Cannot read properties of undefined (reading 'map') in the console. Add a loading state so this doesn’t render before the data arrives.”
Instead of: “can you just put a question mark in front of it” Say: “Add optional chaining here as a safety net, but also find out why this value is undefined and handle the loading and empty states properly.”
Instead of: “it works with my test data but breaks with the real data”
Say: “Log the actual shape of the API response right before the .map() call. I think it doesn’t match what the code assumes.”
People actually ask
“What's the difference between null and undefined in JavaScript?”
undefined is what JavaScript hands you automatically: a variable you declared but never assigned, an argument nobody passed, a property that doesn't exist on an object. null is a value someone chose on purpose, usually to mean 'this exists, but it's empty right now'. They're loosely equal (null == undefined is true) but not strictly equal (null === undefined is false), and typeof null returns 'object', a bug from JavaScript's first version that can't be fixed without breaking old websites.
“Why do I keep getting Cannot read properties of undefined (reading 'map')?”
That error means your code called a method, often .map(), on something that turned out to be undefined at that exact moment, usually because the data it expected (an API response, a database query) hadn't arrived yet, or came back in a different shape than the code assumed. Look upstream of the error line, at whatever produced that undefined value: a missing loading state, a wrong property path, or an API response that changed shape. Optional chaining stops the crash but doesn't explain why the value is missing.
“Does optional chaining (the question mark) fix this error for good?”
It stops the crash: posts?.map(...) returns undefined instead of throwing when posts is undefined or null. It doesn't fix the reason the data is missing, so you can end up with a silently blank list instead of a red error, which is easy to miss while testing. Use it as a safety net while you track down why the value is undefined, usually a skipped loading state or an API response shape that doesn't match what your code expects.
Related terms
Go deeper
Checked against
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Unexpected_type
Just met this in a real session? Glim reads it in plain words.
Paste what your agent just did, a git diff, your terminal, or its summary, and Glim tells you what changed and what to check before you ship. Nothing stored.
Explain my session →