Hello. In this video, I will show you a low level mechanism to handle unexpected errors. So far, we have overlooked error handling. When you run a program, what can go wrong? The user may supply an invalid input, making it impossible for the program to return a result. Or the program may have a bug because of a mistake from a programmer. Or even worse, there is a hardware failure for instance, a remote database is down so you program can't fetch the data it is supposed to fetch. In all these cases, the program can't return a result. What can you do then? A simple option is to abort the execution of the program. But what are the other options if we want to keep the program running? We can report the errors to the end user in case of invalid input or to the programmer in case of bugs in the program. And we can also try to recover from the error by implementing some form of resilience. About error reporting, we want to distinguish between two types of reports. To the user, we want to give informative error messages so that they can fix bad input. To the programmer, we want to give detailed information that relates to the source code to aid with the begging. In practice, what does it mean for a program to not terminate? When something unexpected happens, the execution flow of the program can be interrupted by the runtime environment. The low level language mechanism that is involved is called exceptions. Exceptions can be thrown at any point of the execution of the program, and they interrupt the execution flow unless they are caught by a surrounding exception handler. In Scala, you can throw an exception by using a throw expression. In this method, attemptSomething, we print two lines. We throw an exception with the message, we can't continue and we print another line. We throw the exception by using the keyword throw, followed by the instance of the exception. Here we construct an instance of RuntimeException. Note that, unlike Java, there is no notion of checked exception in Scala. This means that any method can throw any exception at any time without having to declare it in its signature. So if you call the program attemptSomething, it prints the first two lines on the standard output, and then stops when the exception is thrown so it doesn't print the third line. In the runtime environment, there is a default exception handler that prints the stack trace to the standard error before stopping the program. So this is the stack trace. In case you're not familiar with stack traces, the stack trace shows a chain of method calls starting from the position where the error was thrown. Here we see the name of the method in which the exception occurred, attemptSomething, and the source file that defines this method exceptions.scala and the line number 6. On the JVM, the stack trace also shows the name of the class the method belongs to, so here exceptions$package$. This can lead to synthetic names such as exception$package$ for top level definitions in Scala or for object definitions in Scala. You can catch the exceptions thrown by a program by using a try catch handler. Put your program in a try block, in this case, our program just calls attemptSomething, then use a catch block to catch an exception thrown by the program and do something. Here we handle the exception by printing a message to the standard error and then printing the message, stopping the program to the standard output. So now the program prints the first two lines. Then it's throws the exception, which is caught by error handler, which prints this third line and also print this line on the standard error. The syntax for catching exceptions is similar to pattern matching. You match against exceptions by using patterns like here, where we check whether the exception was specifically an ArithmeticException or more general RuntimeException. Catch clauses don't have to be exhaustive. This means that if an exception is thrown, that is not a RuntimeException in this example. This exception won't be caught by this handler, and it will be propagated to the surrounding exception handler, if any, or to the default global exception handler. Exceptions form a type hierarchy that comes from Java, at the top of the hierarchy is the type Throwable. This means that every exception has typed Throwable. Then we have two main branches, the Error branch is for exceptions thrown by the JVM, for instance, when it runs out of memory. Usually there is very little your program can do to recover from these exceptions. The Exception branch is for programs and libraries. Java programs usually signal failures by throwing such exceptions. There are some types of throwables that your program should never try to catch, such as OutOfMemoryError. Because the JVM may not even be able to execute your exception handler in such a situation. We call these exceptions fatal exceptions, so you should never try to catch all the throwables. Instead, you want to catch all the throwables, but the fatal ones. To achieve this, Scala provides a NonFatal extractor that you use like this, case NonFatal of some Throwable. It matches all the exceptions except the fatal exceptions. A try catch block is an expression that returns a value. It can contain a finally clause, optionally, that will be executed in all the cases if no exceptions were thrown, or if an exception was thrown, or if an exception was caught. It is useful to execute cleanup code such as closing files. In summary, exceptions are a low-level mechanism for dealing with unexpected problems during the program execution. Throwing an exception interrupts the program execution unless the exception is caught by a handler.