diff --git a/Web/Scotty/Action.hs b/Web/Scotty/Action.hs
--- a/Web/Scotty/Action.hs
+++ b/Web/Scotty/Action.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE PackageImports #-}
 {-# LANGUAGE CPP               #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RankNTypes        #-}
@@ -78,9 +77,6 @@
 import           Network.Wai (Request, Response, StreamingBody, Application, requestHeaders)
 
 import           Numeric.Natural
-
-import           Prelude ()
-import "base-compat-batteries" Prelude.Compat
 
 import           Web.Scotty.Internal.Types
 import           Web.Scotty.Util (mkResponse, addIfNotPresent, add, replace, lazyTextToStrictByteString, strictByteStringToLazyText)
diff --git a/Web/Scotty/Internal/Types.hs b/Web/Scotty/Internal/Types.hs
--- a/Web/Scotty/Internal/Types.hs
+++ b/Web/Scotty/Internal/Types.hs
@@ -1,8 +1,6 @@
-{-# LANGUAGE PackageImports #-}
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DerivingStrategies #-}
-{-# language DerivingVia #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
@@ -21,6 +19,7 @@
 import           Control.Monad (MonadPlus(..))
 import           Control.Monad.Base (MonadBase)
 import           Control.Monad.Catch (MonadCatch, MonadThrow)
+import           Control.Monad.Error.Class (MonadError(..))
 import           Control.Monad.IO.Class (MonadIO(..))
 import UnliftIO (MonadUnliftIO(..))
 import           Control.Monad.Reader (MonadReader(..), ReaderT, asks)
@@ -44,8 +43,6 @@
 
 import Web.Scotty.Exceptions (Handler(..), catch, catches)
 
-import           Prelude ()
-import "base-compat-batteries" Prelude.Compat
 
 --------------------- Options -----------------------
 data Options = Options { verbose :: Int -- ^ 0 = silent, 1(def) = startup banner
@@ -210,6 +207,15 @@
 
 newtype ActionT m a = ActionT { runAM :: ReaderT ActionEnv m a }
   deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader ActionEnv, MonadTrans, MonadThrow, MonadCatch, MonadBase b, MonadBaseControl b, MonadTransControl, MonadUnliftIO)
+
+-- | Models the invariant that only 'StatusError's can be thrown and caught.
+instance (MonadUnliftIO m) => MonadError StatusError (ActionT m) where
+  throwError = E.throw
+  catchError = catch
+-- | Modeled after the behaviour in scotty < 0.20, 'fail' throws a 'StatusError' with code 500 ("Server Error"), which can be caught with 'E.catch' or 'rescue'.
+instance (MonadIO m) => MonadFail (ActionT m) where
+  fail = E.throw . StatusError status500 . pack
+-- | 'empty' throws 'ActionError' 'AENext', whereas '(<|>)' catches any 'ActionError's or 'StatusError's in the first action and proceeds to the second one.
 instance (MonadUnliftIO m) => Alternative (ActionT m) where
   empty = E.throw AENext
   a <|> b = do
diff --git a/Web/Scotty/Route.hs b/Web/Scotty/Route.hs
--- a/Web/Scotty/Route.hs
+++ b/Web/Scotty/Route.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE FlexibleContexts, FlexibleInstances,
              OverloadedStrings, RankNTypes, ScopedTypeVariables #-}
-{-# language PackageImports #-}
 module Web.Scotty.Route
     ( get, post, put, delete, patch, options, addroute, matchAny, notFound,
       capture, regex, function, literal
@@ -21,9 +20,6 @@
 
 import           Network.HTTP.Types
 import           Network.Wai (Request(..))
-
-import           Prelude ()
-import "base-compat-batteries" Prelude.Compat
 
 import qualified Text.Regex as Regex
 
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,12 @@
 ## next [????.??.??]
 
+## 0.20.1 [2023.10.03]
+
+* remove dependencies on 'base-compat' and 'base-compat-batteries' (#318)
+* re-add MonadFail (ActionT m) instance (#325)
+* re-add MonadError (ActionT m) instance, but the error type is now specialized to 'StatusError' (#325)
+* raise lower bound on base ( > 4.14 ) to reflect support for GHC >= 8.10 (#325).
+
 ## 0.20 [2023.10.02]
 * Drop support for GHC < 8.10 and modernise the CI pipeline (#300).
 * Adds a new `nested` handler that allows you to place an entire WAI Application under a Scotty route (#233).
@@ -12,8 +19,10 @@
 Breaking:
 
 * (#310) Introduce `unliftio` as a dependency, and base exception handling on `catch`.
-** Clarify the exception handling mechanism of ActionT, ScottyT. `rescue` changes signature to use proper `Exception` types rather than strings.
-** All ActionT methods (`text`, `html` etc.) have now a MonadIO constraint on the base monad rather than Monad because the response is constructed in a TVar inside ActionEnv. `rescue` has a MonadUnliftIO constraint. The Alternative instance of ActionT also is based on MonadUnliftIO because `<|>` is implemented in terms of `catch`. `ScottyT` and `ActionT` do not have an exception type parameter anymore.
+* (#310) Clarify the exception handling mechanism of ActionT, ScottyT. `rescue` changes signature to use proper `Exception` types rather than strings. Remove `ScottyError` typeclass.
+* (#310) All ActionT methods (`text`, `html` etc.) have now a MonadIO constraint on the base monad rather than Monad because the response is constructed in a TVar inside ActionEnv. `rescue` has a MonadUnliftIO constraint. The Alternative instance of ActionT also is based on MonadUnliftIO because `<|>` is implemented in terms of `catch`. `ScottyT` and `ActionT` do not have an exception type parameter anymore.
+* (#310) MonadError e (ActionT m) instance removed
+* (#310) MonadFail (ActionT m) instance is missing by mistake.
 
 ## 0.12.1 [2022.11.17]
 * Fix CPP bug that prevented tests from building on Windows.
diff --git a/examples/basic.hs b/examples/basic.hs
--- a/examples/basic.hs
+++ b/examples/basic.hs
@@ -18,8 +18,6 @@
 import Data.Text.Lazy.Encoding (decodeUtf8)
 import Data.String (fromString)
 import Data.Typeable (Typeable)
-import Prelude ()
-import Prelude.Compat
 
 data Err = Boom | UserAgentNotFound | NeverReached deriving (Show, Typeable, Exception)
 
diff --git a/examples/exceptions.hs b/examples/exceptions.hs
--- a/examples/exceptions.hs
+++ b/examples/exceptions.hs
@@ -12,9 +12,6 @@
 import Network.HTTP.Types
 import Network.Wai.Middleware.RequestLogger
 
-import Prelude ()
-import Prelude.Compat
-
 import System.Random
 
 import Web.Scotty.Trans
diff --git a/examples/globalstate.hs b/examples/globalstate.hs
--- a/examples/globalstate.hs
+++ b/examples/globalstate.hs
@@ -17,9 +17,6 @@
 
 import Network.Wai.Middleware.RequestLogger
 
-import Prelude ()
-import Prelude.Compat
-
 import Web.Scotty.Trans
 
 newtype AppState = AppState { tickCount :: Int }
diff --git a/examples/reader.hs b/examples/reader.hs
--- a/examples/reader.hs
+++ b/examples/reader.hs
@@ -10,8 +10,6 @@
 import Control.Monad.Reader (MonadIO, MonadReader, ReaderT, asks, lift, runReaderT)
 import Control.Monad.IO.Unlift (MonadUnliftIO(..))
 import Data.Text.Lazy (pack)
-import Prelude ()
-import Prelude.Compat
 import Web.Scotty.Trans (ScottyT, defaultOptions, get, scottyOptsT, text)
 
 data Config = Config
diff --git a/examples/upload.hs b/examples/upload.hs
--- a/examples/upload.hs
+++ b/examples/upload.hs
@@ -16,8 +16,6 @@
 import qualified Data.ByteString.Lazy as B
 import qualified Data.ByteString.Char8 as BS
 import System.FilePath ((</>))
-import Prelude ()
-import Prelude.Compat
 
 main :: IO ()
 main = scotty 3000 $ do
diff --git a/examples/urlshortener.hs b/examples/urlshortener.hs
--- a/examples/urlshortener.hs
+++ b/examples/urlshortener.hs
@@ -16,9 +16,6 @@
 import Network.Wai.Middleware.RequestLogger
 import Network.Wai.Middleware.Static
 
-import Prelude ()
-import Prelude.Compat
-
 import qualified Text.Blaze.Html5 as H
 import Text.Blaze.Html5.Attributes
 -- Note:
diff --git a/scotty.cabal b/scotty.cabal
--- a/scotty.cabal
+++ b/scotty.cabal
@@ -1,5 +1,5 @@
 Name:                scotty
-Version:             0.20
+Version:             0.20.1
 Synopsis:            Haskell web framework inspired by Ruby's Sinatra, using WAI and Warp
 Homepage:            https://github.com/scotty-web/scotty
 Bug-reports:         https://github.com/scotty-web/scotty/issues
@@ -69,8 +69,7 @@
                        Web.Scotty.Util
   default-language:    Haskell2010
   build-depends:       aeson                 >= 0.6.2.1  && < 2.3,
-                       base                  >= 4.6      && < 5,
-                       base-compat-batteries >= 0.10     && < 0.14,
+                       base                  >= 4.14     && < 5,
                        blaze-builder         >= 0.3.3.0  && < 0.5,
                        bytestring            >= 0.10.0.2 && < 0.12,
                        case-insensitive      >= 1.0.0.1  && < 1.3,
diff --git a/test/Web/ScottySpec.hs b/test/Web/ScottySpec.hs
--- a/test/Web/ScottySpec.hs
+++ b/test/Web/ScottySpec.hs
@@ -141,6 +141,14 @@
           get "/dictionary?word2=y" `shouldRespondWith` "y"
           get "/dictionary?word1=a&word2=b" `shouldRespondWith` "a"
 
+    context "MonadFail instance" $ do
+      withApp (Scotty.get "/" $ fail "boom!") $ do
+        it "returns 500 if not caught" $
+          get "/" `shouldRespondWith` 500
+      withApp (Scotty.get "/" $ (fail "boom!") `rescue` (\(_ :: StatusError) -> text "ok")) $
+        it "can catch the StatusError thrown by fail" $ do
+          get "/" `shouldRespondWith` 200 { matchBody = "ok"}
+
     describe "redirect" $ do
       withApp (
         do
