LogoTRUONG PHAM
Home
Projects
Blogs
YouTube
Contact

Newsletter

Stay updated with technical artifacts and engineering insights.

LogoTRUONG PHAM

Building scalable software and sharing insights on technology & life.

Sitemap

  • Home
  • Projects
  • Blogs
  • YouTube
  • Contact

Connect

  • GitHub
  • LinkedIn
  • Email
  • YouTube

© 2024 TRUONG PHAM. © All rights reserved.

Privacy PolicyTerms of Service
Back
Blog #41: The 2 AM Panic and Infinite Question Marks
50 FRONTEND LESSONS – HARD-EARNED EXPERIENCES

Blog #41: The 2 AM Panic and Infinite Question Marks

Looking back at the time I almost cried over a 'Cannot read property of undefined' error and a lesson in defensive programming.

TP
Truong PhamSoftware Engineer
PublishedAugust 5, 2024

To me in my early years of working,

Do you remember that June night? The night your phone buzzed incessantly at 2 AM because a customer's payment page went completely white (White Screen of Death). You opened your laptop with trembling hands, staring at a console full of bright red errors: Uncaught TypeError: Cannot read property 'address' of undefined.

At that moment, your world felt like it was COLLAPSING. You told yourself: "I tested it so thoroughly locally, how could this happen?".

A Simple but Fatal Problem

To put it most simply: Your project was trying to open a drawer (property) of a cabinet (object) that... didn't exist. In JavaScript, when you access deep inside an object without checking if the upper layers exist, the browser immediately "goes on strike" and stops all operations.

Current Perspective: The Naivety of Trust

Looking back now, I see I was so naive to trust the "promise" of API data. You assumed that if the API returned a user, there would surely be a profile, and if there was a profile, there would surely be an address.

The truth is that in a production environment, anything can happen: An old record missing a data field, a database error causing a return value of null, or simply a slight change on the Backend that you hadn't updated yet.

// How you wrote it then (naive)
const city = user.profile.address.city; 

// How juniors often do it (patchwork)
const city = user && user.profile && user.profile.address && user.profile.address.city;

A common junior mistake is believing that the API is always 100% correct. When encountering this error, you often used a "patchwork" of long && chains. It's not technically wrong, but it makes the code extremely dirty and hard to maintain.

Production vs Local

Why does this error rarely appear locally? Because test data locally is usually "clean" and perfect. But in Production, data is "trash"—it's whatever Users have entered over the last 5 years. That's where the durability of the code is verified.

Comparison of Solutions:

  • Quick fix: Use && operators or nested if/else everywhere to "block" errors.
  • Sustainable way: Use Optional Chaining (?.) combined with Nullish Coalescing (??) to ensure there's always a default value. Further, use a schema validator like Zod to check data as soon as it leaves the API.
// The sustainable way now
const city = user?.profile?.address?.city ?? 'Unknown City';

Practical Lesson

Never access deeply nested data without "insurance." Get into the habit of Defensive Programming. Treat external data as something that cannot be 100% trusted until you've verified it or assigned a default value.

A small question mark ? can save your sleep.


Notes on caution before null values.

Series • Part 41 of 50

50 FRONTEND LESSONS – HARD-EARNED EXPERIENCES

NextBlog #42: When the Backend Changes the Schema and the Fragility of the Frontend
Blog #40: Don't try to be smart – Write code for humans, not for machines
36Blog #36: Touching Legacy Code – When a refactor effort becomes a disaster37Blog #37: The Reusability Trap – When a 'multi-purpose' Component becomes a burden38Blog #38: Micro-frontend Reality Check – When theoretical glory meets harsh reality39Blog #39: The 'Will Fix Later' Promise and the Compound Interest of Technical Debt40Blog #40: Don't try to be smart – Write code for humans, not for machines41Blog #41: The 2 AM Panic and Infinite Question MarksReading42Blog #42: When the Backend Changes the Schema and the Fragility of the Frontend43Blog #43: CORS Isn't Always the Backend's Fault44Blog #44: CI/CD and Environment Variables that 'Disappear' Without a Trace45Blog #45: The Brutal Difference Between Staging and Production46Blog #46: Feature Flag – The 'Lifebuoy' for Risky Releases
TP

Written by Truong Pham

Software Engineer passionate about building high-performance systems and meaningful experiences.

Read more articles