Free tutorials & notes in Hindi & English · Clean code examples 🧰 Free PDF & Image Tools →
⚡ Days 15–22 – Advanced & Async JavaScript  ·  Day 18

Day 18: Errors, try…catch & Debugging

⏱ 90 min📶 Intermediate🎯 100% self-study
Day 18 / 30

✅ Today you will learn

  • Read error messages and stack traces calmly
  • Common error types: TypeError, ReferenceError, SyntaxError, RangeError
  • try…catch…finally and when (not) to use it
  • Throw custom errors and validate early with guard clauses
  • Debug with console, breakpoints, watch and the debugger statement

🏢 In the real world

A real support call: “The checkout button does nothing on my phone.” No error is visible to the customer, the developer cannot reproduce it, and orders are lost. Professional developers spend about half their time debugging. The skill is not avoiding all bugs – it is finding them fast and failing gracefully so the customer sees a helpful message instead of a frozen page.

Reading errors

JavaScript
const tests = [
  () => undefinedVariable + 1,                  // ReferenceError
  () => null.name,                              // TypeError
  () => (42).toUpperCase(),                     // TypeError
  () => new Array(-1),                          // RangeError
  () => JSON.parse('{bad json}'),               // SyntaxError (at runtime, from JSON)
];
for (const t of tests) {
  try { t(); } catch (err) { console.log(`${err.name}: ${err.message}`); }
}
ReferenceError: undefinedVariable is not defined TypeError: Cannot read properties of null (reading 'name') TypeError: 42.toUpperCase is not a function RangeError: Invalid array length SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
ErrorUsually meansTypical fix
ReferenceError: x is not definedTypo or variable out of scopeCheck spelling, declare it, check scope
TypeError: Cannot read properties of null/undefinedElement or data missingCheck selector, defer, use ?. and guards
TypeError: x is not a functionWrong name, or the value is not what you thinkconsole.log(typeof x)
SyntaxErrorBroken code or JSONLook at the line/column, missing ) } ,
RangeErrorNumber out of allowed range / infinite recursionCheck loop and recursion conditions
Uncaught (in promise)A rejected promise with no catchAdd try/catch around await (Day 20)
💡 Read the stack trace bottom-up? No – top-down

The first line is the message, the next line is where it happened (file:line:column). Click it in DevTools to jump to the exact line. Lines below show who called that function.

try…catch…finally

JavaScript
function loadSavedCart(json) {
  try {
    const cart = JSON.parse(json);               // may throw
    console.log('Loaded', cart.items.length, 'items');
    return cart;
  } catch (err) {
    console.log('Could not read the saved cart →', err.name);
    return { items: [] };                        // recover with a safe default
  } finally {
    console.log('finally: runs either way (hide the loader, close the file…)');
  }
}
loadSavedCart('{"items":[{"id":1}]}');
loadSavedCart('{corrupted');
Loaded 1 items finally: runs either way (hide the loader, close the file…) Could not read the saved cart → SyntaxError finally: runs either way (hide the loader, close the file…)

Bad use of try…catch

  • Wrapping the whole app “just in case”
  • catch (e) {} – swallowing errors silently
  • Using it instead of checking for null
  • Hiding bugs you should fix

Good use ⭐

  • Around code that can fail for outside reasons: JSON, storage, network
  • Recover with a default or a clear message
  • Log enough detail to fix it later
  • Re-throw what you cannot handle

Throwing custom errors and guard clauses

JavaScript
class ValidationError extends Error {
  constructor(field, message) {
    super(message);
    this.name = 'ValidationError';
    this.field = field;
  }
}

function createOrder({ name, phone, qty }) {
  // guard clauses: check bad input first, exit early, keep the happy path flat
  if (!name || name.trim().length < 2) throw new ValidationError('name', 'Name is too short');
  if (!/^[6-9]\d{9}$/.test(phone)) throw new ValidationError('phone', 'Invalid mobile number');
  if (!(qty > 0 && qty <= 50)) throw new ValidationError('qty', 'Quantity must be 0–50 kg');
  return { id: 'SS' + 1042, name, phone, qty };
}

for (const input of [{ name: 'Aarti', phone: '9829012345', qty: 2 }, { name: 'Aarti', phone: '12345', qty: 2 }, { name: 'A', phone: '9829012345', qty: 2 }]) {
  try {
    console.log('✅', createOrder(input).id);
  } catch (err) {
    if (err instanceof ValidationError) console.log(`⚠️ ${err.field}: ${err.message}`);
    else throw err;                                  // unknown problem → do not hide it
  }
}
✅ SS1042 ⚠️ phone: Invalid mobile number ⚠️ name: Name is too short

console beyond console.log

JavaScript
const order = { id: 1042, items: [{ name: 'Ghewar', qty: 2 }], total: 1300 };
console.log('plain:', order);
console.warn('⚠️ low stock for Ghewar');             // yellow in DevTools
console.error('❌ payment failed for order', order.id);
console.table(order.items);
console.group('Order 1042');
console.log('customer: Aarti');
console.log('total: ₹' + order.total);
console.groupEnd();
console.time('loop');
let s = 0; for (let i = 0; i < 1e6; i++) s += i;
console.timeEnd('loop');
console.assert(order.total > 0, 'total must be positive');      // prints only if false
console.count('render'); console.count('render');
plain: { id: 1042, items: [ { name: 'Ghewar', qty: 2 } ], total: 1300 } ⚠️ low stock for Ghewar ❌ payment failed for order 1042 ┌─────────┬──────────┬─────┐ │ (index) │ name │ qty │ ├─────────┼──────────┼─────┤ │ 0 │ 'Ghewar' │ 2 │ └─────────┴──────────┴─────┘ Order 1042 customer: Aarti total: ₹1300 loop: 3.209ms render: 1 render: 2

Debugging with breakpoints

  1. 1Reproduce the bug and note the exact steps
  2. 2DevTools → Sources → open your file (Ctrl+P)
  3. 3Click a line number to add a breakpoint (or write debugger; in code)
  4. 4Trigger the action – execution pauses there
  5. 5Hover variables, use Scope and Watch panels to see real values
  6. 6Step over (F10), into (F11), out (Shift+F11); resume (F8)
  7. 7Found it? Fix, then add a test or a guard so it never returns
The professional debugging loop
ToolWhen
Conditional breakpointRight-click a line → pause only when qty > 50
Event listener breakpointsPause on any click or submit without knowing the file
DOM breakpointsElements → right-click → Break on → subtree modifications
Network tabSee requests, status codes and responses (Day 20)
Remote debuggingchrome://inspect to debug a real Android phone over USB

Fail gracefully: global error handling

HTML + JavaScript
<button id="ok">Working button</button>
<button id="bad">Buggy button</button>
<div id="toast" role="alert" hidden style="margin-top:10px;padding:10px 14px;border-radius:10px;background:#fee2e2;color:#7f1d1d"></div>

<script>
// Last line of defence: show a friendly message and report the error
window.addEventListener('error', (event) => {
  const toast = document.querySelector('#toast');
  toast.textContent = 'Sorry, something went wrong. Please try again or call +91 98290 12345.';
  toast.hidden = false;
  console.error('Reported to developers:', event.message, 'at line', event.lineno);
  // in production: send to a logging service (Sentry, your own API) here
});
window.addEventListener('unhandledrejection', (event) => {
  console.error('Unhandled promise:', event.reason);
});

document.querySelector('#ok').addEventListener('click', () => alert('Order button works ✅'));
document.querySelector('#bad').addEventListener('click', () => {
  const cart = null;
  return cart.items.length;          // 💥 TypeError on purpose
});
</script>
▶  Click “Buggy button”: instead of silence, the customer sees a helpful message

🏅 Job skills unlocked today

✔ Recognise error types and read stack traces✔ Use try…catch…finally where failures come from outside✔ Throw custom errors and write guard clauses✔ Debug with console tools, breakpoints and global handlers

Practice tasks

🏋️ Practice – do it yourself

Task 1: Write safeDivide(a, b) that throws a RangeError when b is 0 and returns the result rounded to 2 decimals; call it in try…catch for (10, 4) and (5, 0).
Show solution
JavaScript
function safeDivide(a, b) {
  if (typeof a !== 'number' || typeof b !== 'number') throw new TypeError('Numbers only');
  if (b === 0) throw new RangeError('Cannot divide by zero');
  return Math.round(a / b * 100) / 100;
}
for (const [a, b] of [[10, 4], [5, 0], ['5', 1]]) {
  try { console.log(`${a} / ${b} =`, safeDivide(a, b)); }
  catch (err) { console.log(`${err.name}: ${err.message}`); }
}
10 / 4 = 2.5 RangeError: Cannot divide by zero TypeError: Numbers only
Task 2: Find the bug: const total = items.reduce((s, i) => s + i.price * i.qty) gives “[object Object]…”. Explain and fix.
Show solution
JavaScript
const items = [{ price: 900, qty: 2 }, { price: 500, qty: 1 }];
// Without a start value, s starts as the FIRST OBJECT, so object + number → string
const wrong = items.reduce((s, i) => s + i.price * i.qty);
const right = items.reduce((s, i) => s + i.price * i.qty, 0);
console.log(wrong);
console.log(right);
[object Object]500 2300
Task 3: Put a breakpoint inside the Day 13 order-form submit handler and inspect the FormData values in the Scope panel.

Quick quiz

🧠 Quick Quiz – test yourself

1. “Cannot read properties of null” usually means…
Check selectors and data.
2. finally runs…
Cleanup code.
3. An empty catch (e) {} is…
At least log it.
4. Pause code at a line from inside the code:
Works when DevTools is open.
5. Guard clauses…
Flat happy path.

Interview corner

💼 Interview Corner

How do you debug a bug that only happens in production on mobile?

Collect details (device, browser, steps), check error logging/monitoring for stack traces, reproduce with DevTools device mode and remote debugging (chrome://inspect), check network failures and feature support, add logging around the suspicious code, then fix and add a regression test or guard.

When should you use try…catch?

Around operations that can fail for reasons outside your control – parsing, storage, network, third-party code – where you can recover or show a useful message. Not as a substitute for validation or to silence programming errors.

Summary

  • Read the message and the first stack line; learn the 5 common error types.
  • try…catch…finally around outside failures; recover or re-throw.
  • Custom errors + guard clauses make problems obvious.
  • console methods, breakpoints and global handlers find and contain bugs.
➡️ Next

Day 19: asynchronous JavaScript – the event loop, timers, callbacks and promises.

Frequently Asked Questions

Should I remove console.log before going live?
Remove noisy debug logs; keep meaningful warnings/errors or send them to a logging service. Build tools can strip console.log automatically.
What is source mapping?
When code is minified, source maps let DevTools show and debug your original files and line numbers.
← JavaScript (30 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

Next topicDay 19: Async JS: Event Loop, Callbacks & Promises Your progress: 18 / 30 (60%) · Lesson 19 / 30 Continue →

How was this lesson?

Your feedback helps us make the content better.

Write a review or suggestion (optional)

After approval, your name and city may appear publicly with your review. Please do not write your email or phone number.

▶ CodingEasily on YouTube

Learn with video lessons in easy Hindi

Featured video: RDBMS Part 3 – Class XI Commerce IT

▶ Subscribe – it’s free