Hardik Kamboj

Jun 16, 2025 • 3 min read

Behind the Curtain: How Try-Catch Really Works in JavaScript

Behind the Curtain: How Try-Catch Really Works in JavaScript

You’ve probably written {try-catch} in JavaScript hundreds of times. Feels like magic, right? Error happens, the program doesn’t crash, and the code moves on. But why? What's going on under the hood?

In this blog, I’ll walk you through exactly how JavaScript handles errors, why {try-catch} Let the code live another day, and see what the JavaScript engine, like V8, does behind the scenes. No fluff, just pure breakdown, analogies, bytecode, diagrams, and clarity.


1. What is try-catch?

In plain words, it's a block where you tell JavaScript:

"Yo, this might break. If it does, don’t panic. Here’s how to handle it."

Example

try {
  // risky code
  throw new Error("Something bad happened");
} catch (err) {
  console.log("Caught it:", err.message);
}
console.log("Still running"); 

Output:

Caught it: Something bad happened
Still running 

Cool. But this just tells what happens. Let’s talk about how it happens.


2. Without try-catch, what happens when an error is thrown?

Here’s a minimal example:

function c() {
  throw new Error("💥 boom");
}
function b() {
  c();
}
function a() {
  b();
}
a(); 

What the call stack looks like:

[ a ]
[ b ]
[ c ] 

c() throws an error. JavaScript looks for a handler (a catch block) starting from c, doesn’t find any, so it moves up the stack, to b, then a, then crashes.

No handler? Boom, crash.


3. With try-catch, the game changes

function c() {
  throw new Error("💥 boom");
}
function b() {
  c();
}
function a() {
  try {
    b();
  } catch (err) {
    console.log("Caught:", err.message);
  }
}
a();
console.log("Still alive"); 

Now when c() throws, the engine climbs up the stack and finds a catch in a. Jumps there. Handles error. Continue the code.

No crash.


4. Call Stack + Execution Flow Diagram


5. Wait, but how does JS know where to jump?

That’s where things get juicy.

When the engine parses your code, it doesn’t keep try and catch around in their raw form. It compiles them into bytecode, the lower-level code that the JS engine runs.

And to make error handling possible, it also builds something called a handler table.


6. What is a handler table?

Think of it as a secret map that says:

"If something fails between this instruction and that one, jump to this other place (catch block)."

It looks like this internally:

Try Start Try End Catch Location Byte 10 Byte 30 Byte 50

So when an error is thrown, the engine checks:

  • Am I between byte 10 and 30?

  • Yes? Then jump to byte 50 (that’s your catch block)

Handler Table


7. Okay, but what about the crash?

Without try catch:

  • An error is thrown

  • No entry in the handler table

  • The engine has no idea what to do

  • Program crashes

With try catch:

  • An error is thrown

  • The engine checks the handler table

  • Finds a match

  • Jumps to catch the block

  • Mark's error as handled

  • Execution resumes

Magic? Nah. Just clever compiler engineering.


8. Bytecode Visual Flow

 Source Code ─────► Bytecode
                     │
                     ▼
         ┌────────────────────┐
              Bytecode Block            
              Console.log(...)                
              Throw instruction 
         └────────┬───────────┘
                       ▼
         ┌────────────────────┐
              Handler Table      
              start, end, catch  
         └────────┬───────────┘
                       ▼
         ┌────────────────────┐
                Runtime Engine     
                consults table     
                jumps to catch     
         └────────┬───────────┘
                       ▼
         ┌────────────────────┐
              catch block runs  
              and logs error    
         └────────────────────┘ 

9. TLDR

  • JavaScript engines compile try-catch into bytecode

  • A hidden handler table stores which errors map to which catch blocks

  • When an error is thrown, the engine checks this table and jumps to the catch location

  • If there’s no handler, the program crashes

  • try-atch isn’t just syntax, it’s a controlled escape route built into the engine

See content credentials

Try-Catch Flow


Hope this gave you an inside-out view of try-catch block, which you might be using frequently. If it still feels like magic, that’s okay, you just peeked into the bytecode black box, and that’s more than 99% of devs ever do.


I will be diving deep into more engineering topics or concepts I find interesting, so do follow!


Join Hardik on Peerlist!

Join amazing folks like Hardik and thousands of other people in tech.

Create Profile

Join with Hardik’s personal invite link.

9

26

0