diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+0.4.1
+-----
+* Bump attoparsec upper bound to < 0.14
+* Bump wai-app-static upper bound to < 3.2
+* Bump either upper bound to < 4.5
+
 0.4
 ---
 * `Delete` now is like `Get`, `Post`, `Put`, and `Patch` and returns a response body
diff --git a/example/greet.hs b/example/greet.hs
--- a/example/greet.hs
+++ b/example/greet.hs
@@ -44,7 +44,7 @@
 -- There's one handler per endpoint, which, just like in the type
 -- that represents the API, are glued together using :<|>.
 --
--- Each handler runs in the 'EitherT (Int, String) IO' monad.
+-- Each handler runs in the 'EitherT ServantErr IO' monad.
 server :: Server TestApi
 server = helloH :<|> postGreetH :<|> deleteGreetH
 
diff --git a/servant-server.cabal b/servant-server.cabal
--- a/servant-server.cabal
+++ b/servant-server.cabal
@@ -1,11 +1,10 @@
 name:                servant-server
-version:             0.4.0
+version:             0.4.1
 synopsis:            A family of combinators for defining webservices APIs and serving them
 description:
   A family of combinators for defining webservices APIs and serving them
   .
-  You can learn about the basics in <http://haskell-servant.github.io/getting-started/ the getting started>
-  guide.
+  You can learn about the basics in the <http://haskell-servant.github.io/tutorial tutorial>.
   .
   <https://github.com/haskell-servant/servant/blob/master/servant-server/example/greet.hs Here>
   is a runnable example, with comments, that defines a dummy API and implements
@@ -42,9 +41,9 @@
   build-depends:
         base               >= 4.7  && < 5
       , aeson              >= 0.7  && < 0.9
-      , attoparsec         >= 0.12 && < 0.13
+      , attoparsec         >= 0.12 && < 0.14
       , bytestring         >= 0.10 && < 0.11
-      , either             >= 4.3  && < 4.4
+      , either             >= 4.3  && < 4.5
       , http-types         >= 0.8  && < 0.9
       , network-uri        >= 2.6  && < 2.7
       , mtl                >= 2    && < 3
@@ -54,10 +53,11 @@
       , split              >= 0.2  && < 0.3
       , string-conversions >= 0.3  && < 0.4
       , system-filepath    >= 0.4  && < 0.5
+      , filepath           >= 1
       , text               >= 1.2  && < 1.3
       , transformers       >= 0.3  && < 0.5
       , wai                >= 3.0  && < 3.1
-      , wai-app-static     >= 3.0  && < 3.1
+      , wai-app-static     >= 3.0  && < 3.2
       , warp               >= 3.0  && < 3.1
   hs-source-dirs: src
   default-language: Haskell2010
@@ -114,6 +114,8 @@
               , servant
               , doctest
               , filemanip
+              , directory
+              , filepath
  type: exitcode-stdio-1.0
  main-is: test/Doctests.hs
  buildable: True
diff --git a/src/Servant/Server/Internal.hs b/src/Servant/Server/Internal.hs
--- a/src/Servant/Server/Internal.hs
+++ b/src/Servant/Server/Internal.hs
@@ -227,7 +227,7 @@
 -- >
 -- > server :: Server MyApi
 -- > server = getBook
--- >   where getBook :: Text -> EitherT (Int, String) IO Book
+-- >   where getBook :: Text -> EitherT ServantErr IO Book
 -- >         getBook isbn = ...
 instance (KnownSymbol capture, FromText a, HasServer sublayout)
       => HasServer (Capture capture a :> sublayout) where
@@ -253,7 +253,7 @@
 --
 -- The code of the handler will, just like
 -- for 'Servant.API.Get.Get', 'Servant.API.Post.Post' and
--- 'Servant.API.Put.Put', run in @EitherT (Int, String) IO ()@.
+-- 'Servant.API.Put.Put', run in @EitherT ServantErr IO ()@.
 -- The 'Int' represents the status code and the 'String' a message
 -- to be returned. You can use 'Control.Monad.Trans.Either.left' to
 -- painlessly error out if the conditions for a successful deletion
@@ -329,7 +329,7 @@
 -- | When implementing the handler for a 'Get' endpoint,
 -- just like for 'Servant.API.Delete.Delete', 'Servant.API.Post.Post'
 -- and 'Servant.API.Put.Put', the handler code runs in the
--- @EitherT (Int, String) IO@ monad, where the 'Int' represents
+-- @EitherT ServantErr IO@ monad, where the 'Int' represents
 -- the status code and the 'String' a message, returned in case of
 -- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'
 -- to quickly fail if some conditions are not met.
@@ -425,7 +425,7 @@
 -- >
 -- > server :: Server MyApi
 -- > server = viewReferer
--- >   where viewReferer :: Referer -> EitherT (Int, String) IO referer
+-- >   where viewReferer :: Referer -> EitherT ServantErr IO referer
 -- >         viewReferer referer = return referer
 instance (KnownSymbol sym, FromText a, HasServer sublayout)
       => HasServer (Header sym a :> sublayout) where
@@ -442,7 +442,7 @@
 -- | When implementing the handler for a 'Post' endpoint,
 -- just like for 'Servant.API.Delete.Delete', 'Servant.API.Get.Get'
 -- and 'Servant.API.Put.Put', the handler code runs in the
--- @EitherT (Int, String) IO@ monad, where the 'Int' represents
+-- @EitherT ServantErr IO@ monad, where the 'Int' represents
 -- the status code and the 'String' a message, returned in case of
 -- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'
 -- to quickly fail if some conditions are not met.
@@ -523,7 +523,7 @@
 -- | When implementing the handler for a 'Put' endpoint,
 -- just like for 'Servant.API.Delete.Delete', 'Servant.API.Get.Get'
 -- and 'Servant.API.Post.Post', the handler code runs in the
--- @EitherT (Int, String) IO@ monad, where the 'Int' represents
+-- @EitherT ServantErr IO@ monad, where the 'Int' represents
 -- the status code and the 'String' a message, returned in case of
 -- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'
 -- to quickly fail if some conditions are not met.
@@ -603,7 +603,7 @@
 -- | When implementing the handler for a 'Patch' endpoint,
 -- just like for 'Servant.API.Delete.Delete', 'Servant.API.Get.Get'
 -- and 'Servant.API.Put.Put', the handler code runs in the
--- @EitherT (Int, String) IO@ monad, where the 'Int' represents
+-- @EitherT ServantErr IO@ monad, where the 'Int' represents
 -- the status code and the 'String' a message, returned in case of
 -- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'
 -- to quickly fail if some conditions are not met.
@@ -696,7 +696,7 @@
 -- >
 -- > server :: Server MyApi
 -- > server = getBooksBy
--- >   where getBooksBy :: Maybe Text -> EitherT (Int, String) IO [Book]
+-- >   where getBooksBy :: Maybe Text -> EitherT ServantErr IO [Book]
 -- >         getBooksBy Nothing       = ...return all books...
 -- >         getBooksBy (Just author) = ...return books by the given author...
 instance (KnownSymbol sym, FromText a, HasServer sublayout)
@@ -735,7 +735,7 @@
 -- >
 -- > server :: Server MyApi
 -- > server = getBooksBy
--- >   where getBooksBy :: [Text] -> EitherT (Int, String) IO [Book]
+-- >   where getBooksBy :: [Text] -> EitherT ServantErr IO [Book]
 -- >         getBooksBy authors = ...return all books by these authors...
 instance (KnownSymbol sym, FromText a, HasServer sublayout)
       => HasServer (QueryParams sym a :> sublayout) where
@@ -768,7 +768,7 @@
 -- >
 -- > server :: Server MyApi
 -- > server = getBooks
--- >   where getBooks :: Bool -> EitherT (Int, String) IO [Book]
+-- >   where getBooks :: Bool -> EitherT ServantErr IO [Book]
 -- >         getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...
 instance (KnownSymbol sym, HasServer sublayout)
       => HasServer (QueryFlag sym :> sublayout) where
@@ -810,7 +810,7 @@
 -- >
 -- > server :: Server MyApi
 -- > server = getBooksBy
--- >   where getBooksBy :: Maybe Text -> EitherT (Int, String) IO [Book]
+-- >   where getBooksBy :: Maybe Text -> EitherT ServantErr IO [Book]
 -- >         getBooksBy Nothing       = ...return all books...
 -- >         getBooksBy (Just author) = ...return books by the given author...
 instance (KnownSymbol sym, FromText a, HasServer sublayout)
@@ -849,7 +849,7 @@
 -- >
 -- > server :: Server MyApi
 -- > server = getBooksBy
--- >   where getBooksBy :: [Text] -> EitherT (Int, String) IO [Book]
+-- >   where getBooksBy :: [Text] -> EitherT ServantErr IO [Book]
 -- >         getBooksBy authors = ...return all books by these authors...
 instance (KnownSymbol sym, FromText a, HasServer sublayout)
       => HasServer (MatrixParams sym a :> sublayout) where
@@ -883,7 +883,7 @@
 -- >
 -- > server :: Server MyApi
 -- > server = getBooks
--- >   where getBooks :: Bool -> EitherT (Int, String) IO [Book]
+-- >   where getBooks :: Bool -> EitherT ServantErr IO [Book]
 -- >         getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...
 instance (KnownSymbol sym, HasServer sublayout)
       => HasServer (MatrixFlag sym :> sublayout) where
@@ -940,7 +940,7 @@
 -- >
 -- > server :: Server MyApi
 -- > server = postBook
--- >   where postBook :: Book -> EitherT (Int, String) IO Book
+-- >   where postBook :: Book -> EitherT ServantErr IO Book
 -- >         postBook book = ...insert into your db...
 instance ( AllCTUnrender list a, HasServer sublayout
          ) => HasServer (ReqBody list a :> sublayout) where
diff --git a/src/Servant/Utils/StaticFiles.hs b/src/Servant/Utils/StaticFiles.hs
--- a/src/Servant/Utils/StaticFiles.hs
+++ b/src/Servant/Utils/StaticFiles.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 -- | This module defines a sever-side handler that lets you serve static files.
 --
 -- - 'serveDirectory' lets you serve anything that lives under a particular
@@ -6,10 +7,13 @@
   serveDirectory,
  ) where
 
-import Filesystem.Path.CurrentOS (decodeString)
+import System.FilePath (addTrailingPathSeparator)
 import Network.Wai.Application.Static (staticApp, defaultFileServerSettings)
 import Servant.API.Raw (Raw)
 import Servant.Server (Server)
+#if !MIN_VERSION_wai_app_static(3,1,0)
+import Filesystem.Path.CurrentOS (decodeString)
+#endif
 
 -- | Serve anything under the specified directory as a 'Raw' endpoint.
 --
@@ -32,5 +36,9 @@
 -- handler in the last position, because /servant/ will try to match the handlers
 -- in order.
 serveDirectory :: FilePath -> Server Raw
-serveDirectory documentRoot =
-  staticApp (defaultFileServerSettings (decodeString (documentRoot ++ "/")))
+serveDirectory =
+#if MIN_VERSION_wai_app_static(3,1,0)
+    staticApp . defaultFileServerSettings . addTrailingPathSeparator
+#else
+    staticApp . defaultFileServerSettings . decodeString . addTrailingPathSeparator
+#endif
diff --git a/test/Doctests.hs b/test/Doctests.hs
--- a/test/Doctests.hs
+++ b/test/Doctests.hs
@@ -1,14 +1,18 @@
 module Main where
 
+import           Data.List (isPrefixOf)
+import           System.Directory
+import           System.FilePath
 import           System.FilePath.Find
 import           Test.DocTest
 
 main :: IO ()
 main = do
     files <- find always (extension ==? ".hs") "src"
+    cabalMacrosFile <- getCabalMacrosFile
     doctest $ [ "-isrc"
               , "-optP-include"
-              , "-optPdist/build/autogen/cabal_macros.h"
+              , "-optP" ++ cabalMacrosFile
               , "-XOverloadedStrings"
               , "-XFlexibleInstances"
               , "-XMultiParamTypeClasses"
@@ -16,3 +20,12 @@
               , "-XTypeOperators"
               ] ++ files
 
+getCabalMacrosFile :: IO FilePath
+getCabalMacrosFile = do
+  contents <- getDirectoryContents "dist"
+  let rest = "build" </> "autogen" </> "cabal_macros.h"
+  return $ case filter ("dist-sandbox-" `isPrefixOf`) contents of
+    [x] -> "dist" </> x </> rest
+    [] -> "dist" </> rest
+    xs -> error $ "ran doctests with multiple dist/dist-sandbox-xxxxx's: \n"
+                ++ show xs ++ "\nTry cabal clean"
