# How OCaml exception handling works?

**URL:** https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878
**Category:** Learning
**Tags:** error-handling
**Created:** [August 21, 2023, 10:47pm UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878 "2023-08-21T22:47:50Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![bememol](https://avatars.discourse-cdn.com/v4/letter/b/57b2e6/32.png) [@bememol](https://discuss.ocaml.org/u/bememol)
#### Post date: [August 21, 2023, 10:47pm UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/1 "2023-08-21T22:47:50Z")

</div>

My mind is very hard wired towards using errors as value. I’m mainly a Go developer, I like Erlang and Elixir a lot, and I would like to use Rust more, but I think the language is just way too much. I have lots of worries with OCaml because of the lack of jobs, projects, community size, etc… but it really looks like to be a amazing language to learn and improve as a developer. But I don’t know if I’ll be able to adapt to the whole error handling and this is my question to other developers that came from languages that use errors as values like Go, Rust, and Erlang/Elixir. How do you feel about the overall development experience and error handling?

---

<div class="post-metadata">

### Author: ![shonfeder](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/shonfeder/32/424_2.png) [@shonfeder](https://discuss.ocaml.org/u/shonfeder)
#### Post date: [August 21, 2023, 10:56pm UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/2 "2023-08-21T22:56:20Z")

</div>

OCaml also supports non-exceptional representation of error-prone computations via `Result`/`Either` and `Option`. See [Error Handling · OCaml Tutorials](https://ocaml.org/docs/error-handling)

Erlang also has exceptions: [Erlang -- Errors and Error Handling](https://www.erlang.org/doc/reference_manual/errors.html)

IMO, OCaml’s “errors as values” story is far superior to go’s; and it is just as ergonomic, but less magical than Rust’s.

Rust also has effectual errors, but they are unrecoverable, even tho you’ll find widely used libraries with methods that panic on invalid inputs. That’s not nicer than a slick exception system, imo.

I’d be happy to help with specific questions on these points.

---

<div class="post-metadata">

### Author: ![cemerick](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cemerick/32/1383_2.png) [@cemerick](https://discuss.ocaml.org/u/cemerick)
#### Post date: [August 22, 2023, 3:56am UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/3 "2023-08-22T03:56:23Z")

</div>

I have a similar disposition re: errors as values. Thankfully, almost four years in using OCaml quite heavily in a couple of different contexts, I’ve been able to largely _not_ handle exceptions imperatively. The standard library (and common extensions like Jane Street’s and containers) now offers exception-free implementations for operations that would otherwise raise an exception (e.g. `find_opt` returning an option vs. `find` raising `Not_found`), and _most_ libraries IME likewise provide option and result returns, as appropriate. There are cases where one absolutely does need to be aware of the exception types that might be raised by a particular operation, but they’re rare enough to be the exception to the rule. 😆

---

<div class="post-metadata">

### Author: ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)
#### Post date: [August 23, 2023, 4:25pm UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/4 "2023-08-23T16:25:09Z")

</div>

> [@bememol](#):
>
> How do you feel about the overall development experience and error handling?

Great! 🙂

According to what I have seen, developers with a certain experience are able to sidestep a few minor rough edges here and there (eg in tooling) and quite enjoy the language and appreciate its rock-solid foundations, refactoring power, straight-forward compilation, speed, etc.

Error handling facilities are excellent: exceptions, error values, monads, algebraic effects, … OCaml does not enforce a single style of error handling: you can use whatever fits best in any given situation. This increases complexity somewhat (especially when using third-party libraries which use different error handling styles), but in practice you can produce robust code by following a few simple rules of thumb: error values for “errors” that do not represent an exception situation, exceptions for fatal errors or non-local control flow within library code (but not escaping through the public interface), etc.

Cheers,  
Nicolas

---

<div class="post-metadata">

### Author: ![dangdennis](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dangdennis/32/2594_2.png) [@dangdennis](https://discuss.ocaml.org/u/dangdennis)
#### Post date: [August 23, 2023, 8:50pm UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/5 "2023-08-23T20:50:36Z")

</div>

Is there still a possibility that an exception will still occur for whatever reason, so we might as well add a single root try/catch to prevent the main process from shutting down?

Example: in nodejs or go, you better have that try/catch or rescue because a simple out-of-bounds exception can happen any time, and we wouldn’t want that crashing the main process.

---

<div class="post-metadata">

### Author: ![R\_Huxton](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/r_huxton/32/4216_2.png) [@R\_Huxton](https://discuss.ocaml.org/u/R_Huxton)
#### Post date: [August 23, 2023, 10:58pm UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/6 "2023-08-23T22:58:34Z")

</div>

That possibility is _always_ there for any reasonably complex application.

Pick your favourite “not likely, but is happening somewhere right now” option:

- network failure
- disk failure
- file deleted/permissions changed by superuser
- memory “optimistically” granted by O.S. is now no longer available (this is how they work nowadays)
- user/superuser issued a kill command
- my all-time favourite memory bit flipped by cosmic ray (varies according to altitude)

So, even if “out of bounds” won’t bother you, and “divide by zero” will never happen in _your_ code, if you want to do try and cope with the “real world” have something that catches errors, logs them then cleans up and restarts the process.

---

<div class="post-metadata">

### Author: ![cemerick](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cemerick/32/1383_2.png) [@cemerick](https://discuss.ocaml.org/u/cemerick)
#### Post date: [August 24, 2023, 1:25am UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/7 "2023-08-24T01:25:48Z")

</div>

I’ve written two main types of programs in OCaml:

1. Standalone programs that are meant to be executed for a tightly-defined task. In this context, almost any unexpected failure should rightly be left alone to panic the process. Something higher-level will cope, even if that something else is logged alerts, etc.
2. Web apps, using e.g. Dream et al. These are generally running in an event loop that generally has catch-all exception handling baked in that gives me the opportunity to log the problem(s) and display a reasonable message to the user or perhaps take some alternative path. This doesn’t apply for really egregious cases like OS failures, OOM, etc., where panicking still remains the only available option.

Other contexts may require more special attention.

---

<div class="post-metadata">

### Author: ![dangdennis](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dangdennis/32/2594_2.png) [@dangdennis](https://discuss.ocaml.org/u/dangdennis)
#### Post date: [August 24, 2023, 1:27am UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/8 "2023-08-24T01:27:03Z")

</div>

Right, just making food for thought.

Regarding exceptions, even Haskell has it. I haven’t dug too much into it but how does a system like Rust do away with nearly all exceptions? It seems improbable. They have panics but those are meant for unrecovery errors, meaning that your app would need a complete restart.

In the case of a bit flip, will the rust “runtime” be able to detect a cosmic bit flip that corrupts something entirely? And then be intelligent enough to panic?

I guess at some point, restarting is simply best.

---

<div class="post-metadata">

### Author: ![cemerick](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cemerick/32/1383_2.png) [@cemerick](https://discuss.ocaml.org/u/cemerick)
#### Post date: [August 24, 2023, 1:31am UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/9 "2023-08-24T01:31:41Z")

</div>

Oh, one thing that is worth keeping in mind is that top-level definitions are all executed outside of what you think of as your “main” entry point, and each one _could_ raise an exception, so there’s no “easy” way to really have a “single root try/catch”. So, for all such definitions, you need to do one of:

1. Be _very_ sure that the top-level expression won’t fail (again, aside from truly unrecoverable stuff like OOM).
2. Define them to be lazy values, so that when they are accessed from e.g. inside an event loop, anything bad that happens can be caught and reported cleanly.

Alternatively, you could be very judicious in _not_ having such top-level definitions. This is what I do for my most complex applications, where I have explicit lifecycle abstractions for initializing what would otherwise be top-level values, and then ways for the various parts of the app to access those values from some central context.

---

<div class="post-metadata">

### Author: ![jumpnbrownweasel](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jumpnbrownweasel/32/3062_2.png) [@jumpnbrownweasel](https://discuss.ocaml.org/u/jumpnbrownweasel)
#### Post date: [August 24, 2023, 5:46pm UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/10 "2023-08-24T17:46:44Z")

</div>

> [@dangdennis](#):
>
> Regarding exceptions, even Haskell has it. I haven’t dug too much into it but how does a system like Rust do away with nearly all exceptions? It seems improbable. They have panics but those are meant for unrecovery errors, meaning that your app would need a complete restart.

I think you have a misunderstanding of Rust panics. By default (which is called an unwind panic) they are recoverable and are used in exactly the same way as the unforeseen and unhandled exceptions being discussed. The web server (e.g., Hyper) will catch them and log them, so that other request handlers are not impacted, and you can do the same if you need to.

Rust panics can be configured to abort, meaning they don’t unwind and cannot be recovered from. But doing this is almost always a mistake.

---

<div class="post-metadata">

### Author: ![dangdennis](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dangdennis/32/2594_2.png) [@dangdennis](https://discuss.ocaml.org/u/dangdennis)
#### Post date: [August 24, 2023, 6:47pm UTC](https://discuss.ocaml.org/t/how-ocaml-exception-handling-works/12878/11 "2023-08-24T18:47:22Z")

</div>

Thanks @jumpnbrownweasel.

Reviewed [catch\_unwind in std::panic - Rust](https://doc.rust-lang.org/std/panic/fn.catch_unwind.html) as supplement. Makes sense.
