Syntax Cache
BlogMethodFeaturesHow It WorksBuild a Game
  1. Home
  2. Compare
  3. Python vs JavaScript
  4. Python vs JavaScript Error Handling

Python vs JavaScript Error Handling

Exception handling, custom error types, and resource cleanup in Python versus JavaScript.

try/except vs try/catch

The basic structure is the same: wrap risky code in a try block, handle errors in a catch (JS) or except (Python) block, and optionally run cleanup in finally. The keyword difference -- except vs catch -- is cosmetic, but the binding syntax is not. Python names the caught exception with as: except ValueError as e. JavaScript uses a parenthesized binding: catch (e). Python also lets you catch multiple exception types in a single clause: except (ValueError, TypeError) as e. JavaScript catches everything in one clause and relies on instanceof checks to differentiate. This means Python's error handling is more granular at the syntax level -- you can stack multiple except clauses for different types without nested ifs. JavaScript developers compensate with guard patterns inside catch, but the result is often less readable. Another Python-specific feature: bare except (without a type) catches everything including SystemExit and KeyboardInterrupt, which is almost always a mistake. The Python community strongly discourages bare except in favor of except Exception. JavaScript's catch always catches everything (there is no type filtering), so you must filter manually.

Basic error handling

Python
try:
    result = int("not a number")
except ValueError as e:
    print(f"Failed: {e}")
finally:
    print("cleanup")
JavaScript
try {
  const result = Number.parseInt("not a number");
  if (Number.isNaN(result)) throw new Error("NaN");
} catch (e) {
  console.log(`Failed: ${e.message}`);
} finally {
  console.log("cleanup");
}

Multiple exception types

Python
try:
    data = fetch_data()
except (ConnectionError, TimeoutError) as e:
    handle_network_error(e)
except ValueError:
    handle_bad_data()
JavaScript
try {
  const data = fetchData();
} catch (e) {
  if (e instanceof TypeError) {
    handleNetworkError(e);
  } else if (e instanceof RangeError) {
    handleBadData();
  } else { throw e; }
}
Warm-up1 / 2

Can you write this from memory?

Write a try/except skeleton that catches Exception. Use pass in both blocks.

Python: Python Exception Handling Practice: try/except/else/finally, raise from, custom exceptions →JavaScript: JavaScript Error Handling Practice →

Custom Exceptions and Error Classes

Python custom exceptions inherit from Exception (or a more specific built-in). The convention is a class with a descriptive name and optionally an __init__ that accepts context: class InsufficientFundsError(Exception): def __init__(self, balance): .... JavaScript custom errors extend Error and should set the name property so that stack traces identify them correctly. Both patterns are straightforward, but the ecosystem conventions differ. Python has a rich hierarchy: ValueError, TypeError, KeyError, IndexError, IOError, each with defined semantics. Libraries are expected to raise specific built-in types where appropriate and define custom exceptions for domain-specific failures. JavaScript's built-in hierarchy is flatter: Error, TypeError, RangeError, SyntaxError, ReferenceError. Libraries often throw plain Error with a message string, or use a code property (err.code === "ENOENT"). The result is that Python error handling tends to be more type-driven (catch specific classes), while JavaScript error handling tends to be more value-driven (inspect properties). Neither approach is inherently better, but switching between them requires adjusting your mental model of what a "kind of error" means.

Custom exception / error class

Python
class InsufficientFunds(Exception):
    def __init__(self, balance):
        self.balance = balance
        super().__init__(
            f"Balance too low: {balance}"
        )

raise InsufficientFunds(42)
JavaScript
class InsufficientFunds extends Error {
  constructor(balance) {
    super(`Balance too low: ${balance}`);
    this.name = "InsufficientFunds";
    this.balance = balance;
  }
}
throw new InsufficientFunds(42);
Warm-up1 / 2

Can you write this from memory?

Write a try/except skeleton that catches Exception. Use pass in both blocks.

Python: Python Exception Handling Practice: try/except/else/finally, raise from, custom exceptions →JavaScript: JavaScript Error Handling Practice →

Context Managers vs try/finally

Python's with statement wraps resource acquisition and release into a protocol (__enter__ and __exit__). Opening a file with with open("f.txt") as f: guarantees the file is closed when the block exits, even if an exception fires. JavaScript has no built-in equivalent. The closest patterns are try/finally for synchronous cleanup and the using keyword from the Explicit Resource Management proposal (stage 3, using const handle = ...). Until that proposal ships universally, JavaScript developers write try { ... } finally { resource.close() } or lean on callback-based APIs (fs.readFile). The gap is significant for Python developers who rely on context managers daily -- database connections, locks, temporary directories, HTTP sessions. Python's contextlib module even provides @contextmanager to create custom context managers from generator functions, a pattern that compresses setup/teardown into a few lines. JavaScript's pattern of wrapping cleanup in finally blocks works but scales poorly: nesting three resources means three try/finally levels, while Python handles it with a single with line using the comma syntax (with open(a) as fa, open(b) as fb:). The using proposal will close this gap, but as of early 2026 it remains unavailable in most runtimes without transpilation.

File resource cleanup

Python
with open("data.txt") as f:
    content = f.read()
# file auto-closed here
JavaScript
import { readFile } from "node:fs/promises";
// no built-in "with" equivalent
const content = await readFile(
  "data.txt", "utf-8"
);
// GC handles file descriptor eventually

Custom context manager vs try/finally

Python
from contextlib import contextmanager

@contextmanager
def timer():
    start = time.time()
    yield
    print(f"Elapsed: {time.time() - start:.2f}s")

with timer():
    do_work()
JavaScript
function withTimer(fn) {
  const start = performance.now();
  try {
    return fn();
  } finally {
    const ms = performance.now() - start;
    console.log(`Elapsed: ${(ms/1000).toFixed(2)}s`);
  }
}
withTimer(() => doWork());

Error Propagation Patterns

Both languages propagate exceptions up the call stack automatically -- if nothing catches an error, it bubbles to the top-level handler. The difference lies in async code. Python's async/await propagates exceptions through the coroutine chain exactly like synchronous code, so try/except works identically in async functions. JavaScript's async/await also propagates through the promise chain, but unhandled rejections have historically been silently swallowed (the "unhandled promise rejection" warning). Node.js changed the default to crash on unhandled rejections in v15, aligning closer to Python's behavior. Browser environments still vary. Python's error propagation is straightforward because the language has one execution model with cooperative concurrency bolted on via asyncio. JavaScript's event loop means errors can escape through callbacks, event handlers, setTimeout, and promise chains -- each requiring a different interception strategy (try/catch for sync, .catch() for promises, window.onerror for globals). This fragmentation is a real source of bugs: wrapping only the synchronous portion of an operation in try/catch misses async errors entirely. Python developers moving to JavaScript should adopt the habit of always awaiting promises inside try blocks rather than relying on .catch() callbacks.

Async error handling

Python
import asyncio

async def fetch_data(url):
    raise ConnectionError("timeout")

async def main():
    try:
        data = await fetch_data("/api")
    except ConnectionError as e:
        print(f"Network error: {e}")

asyncio.run(main())
JavaScript
async function fetchData(url) {
  throw new Error("timeout");
}

async function main() {
  try {
    const data = await fetchData("/api");
  } catch (e) {
    console.log(`Network error: ${e.message}`);
  }
}
main();

Practice Both Languages

10 free exercises a day. No credit card required. Build syntax muscle memory with spaced repetition.

Free forever. No credit card required.

← Back to Python vs JavaScript
Syntax Cache

Build syntax muscle memory with spaced repetition.

Product

  • Pricing
  • Our Method
  • Daily Practice
  • Design Patterns
  • Interview Prep

Resources

  • Blog
  • Compare
  • Cheat Sheets
  • Vibe Coding
  • Muscle Memory

Languages

  • Python
  • JavaScript
  • TypeScript
  • Rust
  • SQL
  • GDScript

Legal

  • Terms
  • Privacy
  • Contact

© 2026 Syntax Cache

Cancel anytime in 2 clicks. Keep access until the end of your billing period.

No refunds for partial billing periods.