--- title: try...catch slug: Web/JavaScript/Reference/Statements/try...catch page-type: javascript-statement browser-compat: javascript.statements.try_catch sidebar: jssidebar --- The **`try...catch`** statement is comprised of a `try` block and either a `catch` block, a `finally` block, or both. The code in the `try` block is executed first, and if it throws an exception, the code in the `catch` block will be executed. The code in the `finally` block will always be executed before control flow exits the entire construct. {{InteractiveExample("JavaScript Demo: try...catch statement")}} ```js interactive-example try { nonExistentFunction(); } catch (error) { console.error(error); // Expected output: ReferenceError: nonExistentFunction is not defined // (Note: the exact output may be browser-dependent) } ``` ## Syntax ```js-nolint try { tryStatements } catch (exceptionVar) { catchStatements } finally { finallyStatements } ``` - `tryStatements` - : The statements to be executed. - `catchStatements` - : Statement that is executed if an exception is thrown in the `try` block. - `exceptionVar` {{optional_inline}} - : An optional [identifier or pattern](#catch_binding) to hold the caught exception for the associated `catch` block. If the `catch` block does not use the exception's value, you can omit the `exceptionVar` and its surrounding parentheses. - `finallyStatements` - : Statements that are executed before control flow exits the `try...catch...finally` construct. These statements execute regardless of whether an exception was thrown or caught. ## Description The `try` statement always starts with a `try` block. Then, a `catch` block or a `finally` block must be present. It's also possible to have both `catch` and `finally` blocks. This gives us three forms for the `try` statement: - `try...catch` - `try...finally` - `try...catch...finally` Unlike other constructs such as [`if`](/en-US/docs/Web/JavaScript/Reference/Statements/if...else) or [`for`](/en-US/docs/Web/JavaScript/Reference/Statements/for), the `try`, `catch`, and `finally` blocks must be _blocks_, instead of single statements. ```js-nolint example-bad try doSomething(); // SyntaxError catch (e) console.log(e); ``` A `catch` block contains statements that specify what to do if an exception is thrown in the `try` block. If any statement within the `try` block (or in a function called from within the `try` block) throws an exception, control is immediately shifted to the `catch` block. If no exception is thrown in the `try` block, the `catch` block is skipped. The `finally` block will always execute before control flow exits the `try...catch...finally` construct. It always executes, regardless of whether an exception was thrown or caught. You can nest one or more `try` statements. If an inner `try` statement does not have a `catch` block, the enclosing `try` statement's `catch` block is used instead. You can also use the `try` statement to handle JavaScript exceptions. See the [JavaScript Guide](/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#exception_handling_statements) for more information on JavaScript exceptions. ### Catch binding When an exception is thrown in the `try` block, `exceptionVar` (i.e., the `e` in `catch (e)`) holds the exception value. You can use this {{Glossary("binding")}} to get information about the exception that was thrown. This {{Glossary("binding")}} is only available in the `catch` block's {{Glossary("Scope", "scope")}}. It doesn't need to be a single identifier. You can use a [destructuring pattern](/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring) to assign multiple identifiers at once. ```js try { throw new TypeError("oops"); } catch ({ name, message }) { console.log(name); // "TypeError" console.log(message); // "oops" } ``` The bindings created by the `catch` clause live in the same scope as the `catch` block, so any variables declared in the `catch` block cannot have the same name as the bindings created by the `catch` clause. (There's [one exception to this rule](/en-US/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features#statements), but it's a deprecated syntax.) ```js-nolint example-bad try { throw new TypeError("oops"); } catch ({ name, message }) { var name; // SyntaxError: Identifier 'name' has already been declared let message; // SyntaxError: Identifier 'message' has already been declared } ``` The exception binding is writable. For example, you may want to normalize the exception value to make sure it's an {{jsxref("Error")}} object. ```js try { throw "Oops; this is not an Error object"; } catch (e) { if (!(e instanceof Error)) { e = new Error(e); } console.error(e.message); } ``` If you don't need the exception value, you can omit it along with the enclosing parentheses. ```js function isValidJSON(text) { try { JSON.parse(text); return true; } catch { return false; } } ``` ### The finally block The `finally` block contains statements to execute after the `try` block and `catch` block(s) execute, but before the statements following the `try...catch...finally` block. Control flow will always enter the `finally` block, which can proceed in one of the following ways: - Immediately after the `try` block finishes execution normally (and no exceptions were thrown); - Immediately after the `catch` block finishes execution normally; - Immediately before the execution of a control-flow statement (`return`, `throw`, `break`, `continue`) in the `try` block or `catch` block that would exit the block. If an exception is thrown from the `try` block, even when there's no `catch` block to handle the exception, the `finally` block still executes, in which case the exception is still thrown immediately after the `finally` block finishes executing. The following example shows one use case for the `finally` block. The code opens a file and then executes statements that use the file; the `finally` block makes sure the file always closes after it is used even if an exception was thrown. ```js openMyFile(); try { // tie up a resource writeMyFile(theData); } finally { closeMyFile(); // always close the resource } ``` Control flow statements (`return`, `throw`, `break`, `continue`) in the `finally` block will "mask" any completion value of the `try` block or `catch` block. In this example, the `try` block tries to return 1, but before returning, the control flow is yielded to the `finally` block first, so the `finally` block's return value is returned instead. ```js function doIt() { try { return 1; } finally { return 2; } } doIt(); // returns 2 ``` It is generally a bad idea to have control flow statements in the `finally` block. Only use it for cleanup code. ## Examples ### Unconditional catch block When a `catch` block is used, the `catch` block is executed when any exception is thrown from within the `try` block. For example, when the exception occurs in the following code, control transfers to the `catch` block. ```js try { throw new Error("My exception"); // generates an exception } catch (e) { // statements to handle any exceptions logMyErrors(e); // pass exception object to error handler } ``` The `catch` block specifies an identifier (`e` in the example above) that holds the value of the exception; this value is only available in the {{Glossary("Scope", "scope")}} of the `catch` block. ### Conditional catch blocks You can create "Conditional `catch` blocks" by combining `try...catch` blocks with `if...else if...else` structures, like this: ```js try { myRoutine(); // may throw three types of exceptions } catch (e) { if (e instanceof TypeError) { // statements to handle TypeError exceptions } else if (e instanceof RangeError) { // statements to handle RangeError exceptions } else if (e instanceof EvalError) { // statements to handle EvalError exceptions } else { // statements to handle any unspecified exceptions logMyErrors(e); // pass exception object to error handler } } ``` A common use case for this is to only catch (and silence) a small subset of expected errors, and then re-throw the error in other cases: ```js try { myRoutine(); } catch (e) { if (e instanceof RangeError) { // statements to handle this very common expected error } else { throw e; // re-throw the error unchanged } } ``` This may mimic the syntax from other languages, like Java: ```java try { myRoutine(); } catch (RangeError e) { // statements to handle this very common expected error } // Other errors are implicitly re-thrown ``` ### Nested try blocks First, let's see what happens with this: ```js try { try { throw new Error("oops"); } finally { console.log("finally"); } } catch (ex) { console.error("outer", ex.message); } // Logs: // "finally" // "outer" "oops" ``` Now, if we already caught the exception in the inner `try` block by adding a `catch` block: ```js try { try { throw new Error("oops"); } catch (ex) { console.error("inner", ex.message); } finally { console.log("finally"); } } catch (ex) { console.error("outer", ex.message); } // Logs: // "inner" "oops" // "finally" ``` And now, let's rethrow the error. ```js try { try { throw new Error("oops"); } catch (ex) { console.error("inner", ex.message); throw ex; } finally { console.log("finally"); } } catch (ex) { console.error("outer", ex.message); } // Logs: // "inner" "oops" // "finally" // "outer" "oops" ``` Any given exception will be caught only once by the nearest enclosing `catch` block unless it is rethrown. Of course, any new exceptions raised in the "inner" block (because the code in `catch` block may do something that throws), will be caught by the "outer" block. ### Returning from a finally block If the `finally` block returns a value, this value becomes the return value of the entire `try-catch-finally` statement, regardless of any `return` statements in the `try` and `catch` blocks. This includes exceptions thrown inside of the `catch` block: ```js (() => { try { try { throw new Error("oops"); } catch (ex) { console.error("inner", ex.message); throw ex; } finally { console.log("finally"); return; } } catch (ex) { console.error("outer", ex.message); } })(); // Logs: // "inner" "oops" // "finally" ``` The outer "oops" is not thrown because of the return in the `finally` block. The same would apply to any value returned from the `catch` block. ## Specifications {{Specifications}} ## Browser compatibility {{Compat}} ## See also - {{jsxref("Error")}} - {{jsxref("Statements/throw", "throw")}}