Error Handling in JavaScript: Try, Catch, Finally

Code fatega, tension mat lo — sambhalna aana chahiye
JavaScript runs. But sometimes it crashes.
Your code breaks. App stops. User sees blank screen.
That's bad.
But what if you could catch the error and handle it gracefully?
Enter try, catch, finally.
The Problem: Code That Crashes
const user = null;
console.log(user.name); // TypeError: Cannot read property 'name' of null
Your entire app stops. Everything after this line? Dead.
One small mistake, whole app down.
What Are Errors in JavaScript?
Errors happen when JavaScript can't execute code properly.
Common errors:
| Error Type | When it happens |
|---|---|
| ReferenceError | Variable doesn't exist |
| TypeError | Wrong type (null.name) |
| SyntaxError | Wrong syntax (missing }) |
| RangeError | Value out of range (array length -1) |
// ReferenceError
console.log(unknownVar);
// TypeError
[1, 2, 3].map(null);
// SyntaxError (won't even run)
const a = {;
// RangeError
const arr = new Array(-1);
What is Try...Catch?
Try = try to run risky code. Catch = if error happens, run this instead.
try {
const user = null;
console.log(user.name); // Error happens here
console.log("This won't run");
} catch (error) {
console.log("Something went wrong:", error.message);
}
console.log("App continues...");
// Output:
// Something went wrong: Cannot read property 'name' of null
// App continues...
App didn't crash. It kept running.
Try...Catch Flow Diagram
The Catch Error Object
Catch gives you an error object with useful info:
try {
throw new Error("Something bad happened");
} catch (err) {
console.log(err.name); // "Error"
console.log(err.message); // "Something bad happened"
console.log(err.stack); // Full stack trace
}
Finally Block — Jo Bhi Ho, Chalega
Finally runs every time — whether error happened or not.
try {
console.log("Trying...");
// No error
} catch (err) {
console.log("Catch:", err);
} finally {
console.log("Finally: Cleanup work here");
}
// Output:
// Trying...
// Finally: Cleanup work here
With error:
try {
console.log("Trying...");
throw new Error("Oops");
} catch (err) {
console.log("Catch:", err.message);
} finally {
console.log("Finally: Still runs");
}
// Output:
// Trying...
// Catch: Oops
// Finally: Still runs
Try → Catch → Finally Execution Flow
Throwing Custom Errors
You can create your own errors with throw.
function divide(a, b) {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
return a / b;
}
try {
const result = divide(10, 0);
console.log(result);
} catch (err) {
console.log("Error:", err.message);
}
// Output:
// Error: Division by zero is not allowed
Custom Error Types
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
try {
const age = -5;
if (age < 0) {
throw new ValidationError("Age cannot be negative");
}
} catch (err) {
if (err instanceof ValidationError) {
console.log("Validation:", err.message);
} else {
console.log("Other error:", err);
}
}
Why Error Handling Matters
| Without error handling | With error handling |
|---|---|
| App crashes | App continues |
| User sees blank screen | User sees friendly message |
| Hard to debug | Clear error logs |
| Bad user experience | Graceful failure |
Example: API call with vs without try-catch
// Without try-catch (bad)
async function getUser() {
const response = await fetch("/api/user");
const data = await response.json();
console.log(data.name);
}
// If network fails → entire app crashes
// With try-catch (good)
async function getUser() {
try {
const response = await fetch("/api/user");
const data = await response.json();
console.log(data.name);
} catch (error) {
console.log("Failed to load user. Please try again.");
// Show friendly message to user
}
}
Common Mistakes
Mistake 1: Not catching async errors
// ❌ Try-catch won't catch async errors directly
try {
setTimeout(() => {
throw new Error("Oops"); // This crashes the app
}, 1000);
} catch (err) {
console.log("Caught:", err); // Never runs
}
// ✅ Catch inside the async callback
setTimeout(() => {
try {
throw new Error("Oops");
} catch (err) {
console.log("Caught:", err.message);
}
}, 1000);
Mistake 2: Empty catch block
try {
riskyCode();
} catch (err) {
// Empty — bad! You'll never know what happened
}
Always log or handle the error.
Real-World Examples
Example 1: Form validation
function validateForm(formData) {
try {
if (!formData.name) throw new Error("Name is required");
if (formData.age < 18) throw new Error("Must be 18+");
if (!formData.email.includes("@")) throw new Error("Invalid email");
console.log("Form submitted");
return true;
} catch (err) {
alert(err.message);
return false;
}
}
Example 2: JSON parsing
function parseUserData(jsonString) {
try {
const user = JSON.parse(jsonString);
console.log("User:", user);
return user;
} catch (err) {
console.log("Invalid JSON received");
return null;
}
}
parseUserData('{"name":"Batman"}'); // Works
parseUserData("not json"); // Invalid JSON received
Example 3: File reading (Node.js style)
const fs = require('fs');
try {
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);
} catch (err) {
console.log("File not found. Creating default...");
fs.writeFileSync('file.txt', 'default content');
}
Try-Catch Performance Note
Try-catch has a small performance cost. Don't wrap every line.
Use where errors are likely:
API calls
JSON parsing
User input validation
File operations
Don't use where errors are unlikely:
Simple math
String concatenation
Final Thought
Code fatega. That's normal.
But app crash nahi hona chahiye.
Try-catch let's you fail gracefully — show friendly message, log the error, keep the app running.Finally block is for cleanup.
Throw your own errors for validation.




