Skip to content
Extensible exceptions for servant
Branch: master
Clone or download
dbaynard Merge pull request #7 from ch1bo/feat/split-modules
Split into separate core and server modules
Latest commit f5edc71 Nov 18, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
servant-exceptions Split off server module Nov 17, 2018
.travis.yml Merge branch 'master' into feat/split-modules Nov 17, 2018 Release 0.1.1 Jan 23, 2018
LICENSE Initial commit Nov 27, 2017 Add build status to README Nov 17, 2018
stack.yaml Split off server module Nov 17, 2018

servant-exceptions Build Status

Servant servers typically run their handlers in some form of IO. Either directly in the builtin Handler monad or a custom monad transformer on top it. When APIs fail, one would typically use the MonadError ServantError instance via throwError to create an error response of type ServantErr.

This approach has two problems:

  • Handler (basically being ExceptT ServantErr IO) is considered an anti-pattern by some, as it suggests to novice users that only ServantErr would occur, but in IO any exception can be raised to abort execution
  • ServantErr values need to be created at the call site of throwError, where the requested content type and/or headers are not available

servant-exception tries to help with both by making it easy to catch specific error types with an instance of Exception and provide automatic encoding into the requested content-type.

The API combinator Throws e can be used to catch exceptions of type e in the server, for example:

type API = "api" :> Throws UsersError :> "users" :> Get '[JSON, PlainText] [User]

The type UsersError can then be used to describe expected errors and their conversion via type class instances:

data UsersError = UserNotFound
                | UserAlreadyExists
                | InternalError
                deriving (Show)

instance Exception UsersError

instance ToServantErr UsersError where
  status UserNotFound = status404
  status UserAlreadyExists = status409
  status InternalError = status500

instance ToJSON UsersError where
  toJSON e = object [ "type" .= show (typeOf e)
                    , "message" .= message e

instance MimeRender PlainText UsersError where
  mimeRender ct = mimeRender ct . show


This package is still a work-in-progress and lacks at least

  • Documentation, more examples
  • servant-client support
  • servant-docs support


This package is inspired by servant-checked-exceptions (Throws combinator) and the generalized error handling in cardano-sl.

You can’t perform that action at this time.