An attempt at a Haskell Servant API - repetition of Left/Right case matching
Here's how to use ExceptT to brighten the day a little. You may have hoped for a way to do handle only once after combining the Handlers with :&lt;|&gt;... but I also don't know how to do that. If withExceptT went to arbitrary MonadError instances, handle could have been more concise.

import Control.Monad.Trans.Except

siteServer :: Server SiteAPI
siteServer = site :&lt;|&gt; addPage where
  handle :: ExceptT String IO a -&gt; Handler a
  handle = liftIO . runExceptT &gt;=&gt; \case
    Left err -&gt; throwError $ err404 { errBody = "Site not found!" &lt;&gt; BS.pack err }
    Right x -&gt; return x

  site :: Int -&gt; Handler Site
  site i = handle $ ExceptT $ loadSite i

  addPage :: Int -&gt; Page -&gt; Handler ()
  addPage i p = handle $ do
    Site name pages &lt;- ExceptT $ loadSite i
    withExceptT (\e -&gt; "Failed to write to file: " ++ show i ++ ". " ++ show (e :: IOException))
      $ ExceptT $ try $ BS.writeFile (getSiteFilename i) $ encode $ Site name $ p:pages