Easing into Functional Error Handling in Scala

This post was originally published on longcao.org in June of 2015 and is republished below.

One of the biggest selling points of Scala is being able to transition from Java to the world of functional programming. What this means, practically speaking, is that you and/or your team can start off writing very Java-like Scala that already works, treating it as a “better Java” with more goodies and less verbose syntax. But why stop at that? We can do better by adopting more typesafe functional concepts, and the best part is we can ease ourselves into at least one practical application without drowning: functional error handling.

On Exceptions

Java has the concept of checked exceptions, where you have to explicitly catch exceptions or declare the method can throw, and in doing so the compiler can provide some assistance in enforcing error handling to a degree, in theory. In practice, it too easily became nothing short of a nightmare for Java developers, but that’s another story.

Scala only has unchecked exceptions. This can be a problem when you’re trying to transition to a more functional style, because it breaks what’s called referential transparency [1]: that an expression can be replaced with its value without changing prior behavior. Boiling it down succinctly: that a function always returns exactly what it says it returns given the same set of inputs with no side effects.

An Exceptional Example

Here’s a model program showing a simple flow of buying and making coffee (can you tell I am really into coffee?), where our functions aren’t technically pure:

In the example above, the functions buyBeans  and brewCoffee  effectively lie to you. In their type signatures, the function says it should always return a type given another (in the form of A => B ), but according to their inner logic they may throw an exception. This breaks functional purity since these functions no longer always returns exactly the right type, in the case of buyBeans , if you don’t have enough money it will throw an exception. In this case, the compiler won’t tell you about a violation of functional purity by failing to compile.

Here’s the hard truth if you’re very used to this style of error handling but want to continue down the path of functional zen: stop throwing exceptions in your own code. That means not using them for logic control, ‘object not found’ errors, or anything like that. Granted, there will always be library code that throws exceptions, including in the standard library, but those should be explicitly handled where possible (one approach is mentioned below) and not be allowed to bubble out.

Improving Over Exceptions

Why, you ask, would we want to ‘improve’ our code by not using exceptions? For someone coming from Java and the like, exceptions are familiar, easy to insert into code, and provide things like stack traces. What’s not to like about that? Let’s iron out the reasons to the contrary before diving into examples.

Our biggest reason has already been mentioned: pursuing functional purity, and therefore making it easier to substitute values as we read through code. No sneaky functions secretly masquerading as potential exceptions in disguise! Other benefits include monadic composition [2] and taking advantage of Scala’s for-comprehension sugar. Another effect of all this is that most of these container types also short circuit upon error – when an error occurs then the rest of the downstream logic isn’t executed and the result is a type containing the first error encountered. This is similar to unhandled exceptions, except now that we’re using container types, the compiler will definitely complain if you don’t explicitly handle it.

The neat little conclusion is that in embracing functional composition, you can effectively linearize your code flow (with some detours when necessary) and prioritize in laying out the happy path in your code.


Let’s get hands on: how do we go forward with error handling if we take away exceptions? Since this function results in either getting a back a coffee or not, one of the first things we can reach for is to use the Option. It is a good first choice for exactly this case: after applying the function’s logic, there’s either Some(value)  or None .

Pay attention to what happened to purchaseCoffee  – we chained buyBeans  and brewCoffee  together using a for-comprehension! If for some reason buyBeans  returns a None , the logic will short circuit and purchaseCoffee  will end up returning a None  in the end, effectively bypassing brewCoffee . This is something we can call biasing, where application of a function to these container types is biased to one result over the other – in this case we bias to Some  and the underlying flatMap  used in the for-comprehension syntactic sugar is really only meaningful for that case.


As previously mentioned, there’s also another approach to refactoring exception-laden code: Try. Try  can be thought of as a container type that results in either a Success(value) or a Failure(exception) , and the creation of a Try  is useful to wrap code which at any point may throw an exception. It may be pragmatic to drop in Try  instead of Option  especially if you are dealing with third party libraries or logic for which the refactoring may be too ambitious to attempt all at once. Try , like Option , is biased for the case that results in a value, Success .


There are some minor problems with Option  and Try , however: Option  doesn’t necessarily provide you enough context as to why a computation failed and Try ‘s failure mechanism still relies on exceptions, which we’ve assumed to disavow. Enter Either, which represents the disjoint union of two types (either type A or type B) and may be more useful for us to provide context for failure without an exception: one type can represent a success result and the other can represent a failure or error.

An important detail to note is that Either  itself does not have the map  and flatMap  methods nor is biased towards a side. Left  is adopted by convention to hold an error while Right  is assumed as the value itself. Instead, to get flatMap  capabilities we have to use Either ‘s projections to force a right-bias by calling the .right  projection on these Either s, but that probably violates your DRYness sensibilities, no? We can improve yet further with alternatives from outside the standard library.

Library Alternatives

In the Scala ecosystem, there are some alternative error handling container types, the ones described below are isomorphic (similar in form and purpose) to the standard library’s Either , except most make a decision on biasing and provide quite a bit more methods in their definitions.


Similar to Either  is scalaz.\/  (commonly pronouced as disjunction), which is also a disjoint union, except scalaz.\/  is right-biased where the right side is considered to be the success case and the left side to be the error case. scalaz.\/  also has additional methods not available in Either  such as flatMap   – which is one of the reasons we can use this directly in for-comprehensions.

*Note: The A \/ B syntax, infix type notation, probably looks strange to you and it is! For some reason it’s not very well mentioned nor seen much in mainstream Scala code, but seems to be especially prevalent in the discussion of functional error handling. In this case, A \/ B is sugar for \/[A, B] .


Another disjoint union type but out of the Scalactic library, Or differs slightly by being left-biased and reads like “the good value or a bad value/error”. Usage of Or  with infix type parameters is encouraged since the type name then flows like natural language: the Good  value Or  the Bad  value.


Yet another disjoint union type isomorphic to the rest of these, Xor comes from the promisingly nascent Cats typeclass library for Scala. Cats is still under heavy initial development and can best be currently seen as a something to keep an eye on, but nonetheless is worthwhile mentioning due to the buzz around it. Xor  is right-biased and also benefits from being written out in infix notation.


As with many engineering decisions, there are tradeoffs in choosing one way or another – functional error handling is no exception. The payoffs are well worth it, but it is also prudent to mention some things that should be taken into consideration:

  • Library dependencies on scalaz , scalactic , or cats  – not a trivial decision. These are large libraries which your team may not be ready for. Consider carefully if you want to go outside the standard library.
  • Possible performance hits – admittedly, this is an area where I have little expertise (but do I smell a possible follow-up post on benchmarking this?), but do keep in mind that in evolving from Java-like code to more functional code there may be performance hits, e.g. more allocations for all these little types which may lead to GC issues.
  • Mind your boundaries – if you’re writing a library you may be exposing clients (or consumers, or colleagues) to something they’ve never seen before that may turn them off immediately: consider providing bridging-the-gap conveniences for handling these types! Usability goes a long way for everyone.

What about accumulating errors?

As mentioned before, all these error handling types fail fast, so there’s no room for accumulating errors along a group of functions. In a future post we’ll go over mechanisms for accumulating errors, some of which will look familiar, and some look very different from what someone coming from Java has ever seen.

Further Reading

There are also other great resources on the topic specifically for Scala that I wholly recommend to read:

[1] Or purity, whatever. Before you break out the “well, actually…“, see a discussion on the terms purity vs. referential transparency, and for the purpose of this post I may interchange both.

[2] Monads and monadic composition (function composition) are a hard thing to explain well, I like to boil it down to being boxes for values that come with built-in behavior. Functors, Applicatives, And Monads In Pictures is so far my favorite explainer, complete with pictures!

A Picture of Long Cao


Long Cao is a software engineer at MediaMath in New York City. A Houston native, he is interested in Scala, Clojure, Play, functional programming, natural language processing, and machine learning. You can find his thoughts at longcao.org, his photography at sotohp.tumblr.com, and his person at the local coffeeshop.

2 responses to “Easing into Functional Error Handling in Scala”

  1. Nice article.

    One note: scalactic.Or also has a companion concept “Every[T]” which allows you accumulate errors:

    like this:

    import Accumulation._

    def parsePerson(inputName: String, inputAge: String): Person Or Every[ErrorMessage] = {
    val name = parseName(inputName)
    val age = parseAge(inputAge)
    withGood(name, age) { Person(_, _) }


Leave a Reply

Your email address will not be published. Required fields are marked *