Try and Rescue: Turning Failures into Clear Results

Welcome. In this course, you will learn how Elixir handles errors and builds fault-tolerant systems. Since this is our first unit, we will start with exceptions and how to convert them into predictable return values using try/rescue. This pattern is useful when you want to keep a function pure and return {:ok, value} or {:error, reason} instead of crashing.

Handling Arithmetic Errors with Try/Rescue

What it does:

  • The try block attempts a / b.
  • If b is 0, Elixir raises an ArithmeticError, which we rescue and convert to {:error, "Cannot divide by zero"}.
  • The second rescue clause matches any other exception, binds it to e, and returns a friendly error string. This keeps the function’s contract stable: always return {:ok, value} or {:error, reason}.

Why it matters:

  • In production, a simple math mistake should not bring down your process. Converting exceptions to tagged tuples makes failures explicit and easy to handle with pattern matching.

Note: rescue matches exceptions; catch is for low-level Erlang “throws” and is rarely needed in day-to-day Elixir. For example, you might see throw/ used for non-local returns in legacy code, but idiomatic Elixir almost always prefers exceptions and . Prefer rescuing specific exception types when possible.

Parsing Input Safely and Inspecting Results

What it does:

  • String.to_integer/1 raises ArgumentError on bad input (like "abc"). We rescue that and return {:error, "Invalid integer format"}.
  • IO.inspect shows the outcomes:
    • ErrorHandler.safe_divide(10, 2) -> {:ok, 5.0}
    • ErrorHandler.safe_divide(10, 0) -> {:error, "Cannot divide by zero"}
    • ErrorHandler.parse_integer("42") -> {:ok, 42}
    • ErrorHandler.parse_integer("abc") -> {:error, "Invalid integer format"}

Design takeaway:

  • This approach gives you a clean, uniform interface. Callers can pattern match on {:ok, value} or without worrying about exceptions leaking out.
Summary and What Comes Next

You learned how to:

  • Use try/rescue to catch exceptions and return stable tuples within a module.
  • Rescue specific exception types (ArithmeticError, ArgumentError) and provide clear error messages.
  • Keep your public API predictable by avoiding raised exceptions at call sites.
  • Prefer “let it crash” with supervision for many real-world errors, using try/rescue mainly for boundary cases or when interacting with code that raises.

You are ready to practice transforming exceptions into friendly results and inspecting them. The next step will be hands-on — let’s put this pattern to work and build your confidence.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal