cats-mtl-typed-errors
Cats MTL Typed Errors (Scala)
Quick start
- Define a domain error type; it may or may not extend Throwable depending on context.
- Use Cats MTL
Raise[F, E]in functions that can raise errors. - Use
Handle.allow/rescue(Scala 3) orHandle.allowF(Scala 2) to introduce a scoped error capability and handle it like try/catch. - Prefer Cats MTL over
IO[Either[E, A]]and avoidEitherT[IO, E, A]; pure functions returningEither[E, A]are fine at API boundaries. F[_]is optional: you can writeIO-specific code or keepF[_]for polymorphism, depending on the project.
Workflow
- Model domain errors as sealed ADTs (Scala 2) or enums (Scala 3)
- For effectful code that can raise errors, require
Raise[F, E](andMonad[F]orApplicative[F]). - Raise errors with
.raiseand return successful values withpure. - At a boundary, use
Handle.allow(Scala 3) orHandle.allowF(Scala 2) to create a scope where raises are valid. - Close the scope with
.rescueto handle each error case explicitly. - Keep Cats Effect resource and concurrency semantics intact by staying in the monofunctor error channel.
Patterns to apply
- Typed errors in signatures: treat the error type parameter
Eas the checked-exception channel in the function signature. - Scoped error capabilities: require
Raise[F, E]in functions that can fail; useHandle[F, E]when you also need to recover. - Scala 3 ergonomics: prefer
usingand context functions withallow; type inference is significantly better. - Scala 2 compatibility: use
allowFand explicit implicit parameters; expect more braces and explicit types. - Interop with pure code: use pure
Either[E, A]for parsing/validation and lift intoFwhere needed. - Avoid transformer stacks: do not reach for
EitherTjust to get a typed error channel; Cats MTL provides the capability without the stack. - Avoid sealed-on-sealed inheritance: model error hierarchies with composition (wrapper case classes), not sealed inheritance chains.
References
- Load
references/custom-error-types.mdfor detailed guidance, Scala 2/3 syntax, and rationale from the Typelevel article.
More from alexandru/skills
cats-effect-io
Scala functional programming with Cats Effect IO and typeclasses. Use for wrapping side effects, modeling purity, choosing Sync/Async/Temporal/Concurrent, handling blocking I/O, and composing resources, fibers, and concurrency safely.
39cats-effect-resource
Scala resource lifecycle management with Cats Effect `Resource` and `IO`. Use when defining safe acquisition/release, composing resources (including parallel acquisition), or designing resource-safe APIs and cancellation behavior for files, streams, pools, clients, and background fibers.
36akka-streams
Scala reactive streaming with Akka Streams and Pekko Streams. Use for dataflow and reactive programming patterns, testing stream components, and understanding when NOT to use streams (prefer plain functions for transformations and I/O).
20arrow-typed-errors
Kotlin + Arrow typed error handling using Raise DSL and wrapper types (Either/Option/Ior/Result/nullable), including validation with accumulation, interop with exceptions, and custom error wrappers. Use for designing or refactoring error modeling, converting exception-based flows, building smart constructors, accumulating validation errors, or integrating Outcome/Progress-style wrappers with Arrow.
16kotlin-java-library
Kotlin design for Java libraries and Java consumers. Use when building Kotlin code intended for Java callers, aligning with Java interop, JVM annotations, records, and backward/binary compatibility rules.
14jspecify-nullness
JSpecify nullness annotations for Java APIs and tooling. Use when adopting or migrating JSpecify annotations, designing null-safe Java signatures and generics, or interpreting tool conformance and Kotlin interop.
13