If there is an exception a matching error handler will be selected and called in the context of the error. A default handler could be a debugger, a break loop (which is a Lisp REPL), something which asks the user waht to do or it could be a handler provided by the software, which could do anything, including looking for restarts and using one.
For example the variable a is unbound and we try to add 3.
CL-USER 37 > (+ 3 a)
CL shows an UNBOUND-VARIABLE error and provides Restarts. Restart 3 is a USE-VALUE restart.
Error: The variable A is unbound.
1 (continue) Try evaluating A again.
2 Return the value of :A instead.
3 Specify a value to use this time instead of evaluating A.
4 Specify a value to set A to.
5 (abort) Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
We are now in a break loop, a REPL one level deeper, in the context of the error. Let's see what the condition (-> exception) is:
we call one restart (listed above, number 3) interactively, it uses the new value and continues to compute the expression. It asks for a value. I enter 5 -> 5 + 3 = 8
CL-USER 39 : 1 > :c 3
Enter a form to be evaluated: 5
8
We can do it also programmatically. HANDLER-BIND establishes a handler for UNBOUND-VARIABLE. It invokes the restart USE-VALUE with 4 -> 3 + 4 = 7
In the CL condition system they have separated error detection (exception thrown) from handler selection (catching exception) and handler implementation (what are called "restarts".)
So basically instead of registering one handler (catch block) that is responsible both for determining the proper course of action and implementing it, the condition system allows you to register multiple "restarting points" which the handler can select from when deciding how to handle the error.
One of the restarts often used in debugging is restarting any of the functions in the call chain, i.e. just trying the same thing again. But just as common is varying some parameter or local variable and then restarting the function.
The process hasn’t crashed after an exception. It still might even exit with a success error code, if you really want it to.
An exception is raised when you attempt to parse HTML as JSON. The process doesn’t end. You catch the exception, see what happened, and respond with a 400.