The Finally Block

While try/catch is the most common error-handling construct, there is an optional third block you can append: the finally block.

Code placed inside the finally block is guaranteed to execute no matter what happens in the preceding try or catch blocks.

Why use finally?

It is typically used for “cleanup” operations. For example, if you open a database connection in a try block, you must ensure that the connection is closed, regardless of whether the query succeeded or failed.

try {
  const user = {};
  console.log(user.profile.age); // Throws an error
} catch (err) {
  console.log("Caught:", err.message);
} finally {
  // This will ALWAYS run
  console.log("Executing cleanup operations...");
}

// Output:
// Caught: Cannot read properties of undefined (reading 'age')
// Executing cleanup operations...

Handling Catch Errors

In rare scenarios, the code inside your catch block might actually throw an error itself! If this happens, the program will crash, but the finally block will still execute before the crash takes down the environment.

function riskyCleanup() {
  try {
    throw new Error("Initial failure");
  } catch (err) {
    // We throw another error inside the catch!
    throw new Error("Secondary failure inside catch");
  } finally {
    // This still runs before the program halts
    console.log("Cleanup complete");
  }
}