diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## Version 1.5.8
+
+- Require mtl-2.2.1 or newer
+  [#448](https://github.com/haskell-tls/hs-tls/pull/448)
+
 ## Version 1.5.7
 
 - New APIs: getFinished and getPeerFinished
diff --git a/Network/TLS/Core.hs b/Network/TLS/Core.hs
--- a/Network/TLS/Core.hs
+++ b/Network/TLS/Core.hs
@@ -56,6 +56,7 @@
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Char8 as C8
 import qualified Data.ByteString.Lazy as L
+import           Control.Monad (unless, when)
 import qualified Control.Exception as E
 
 import Control.Monad.State.Strict
diff --git a/Network/TLS/ErrT.hs b/Network/TLS/ErrT.hs
--- a/Network/TLS/ErrT.hs
+++ b/Network/TLS/ErrT.hs
@@ -10,20 +10,12 @@
 module Network.TLS.ErrT
     ( runErrT
     , ErrT
-    , Error(..)
     , MonadError(..)
     ) where
 
-#if MIN_VERSION_mtl(2,2,1)
-import Control.Monad.Except
-import Control.Monad.Error.Class (Error(..))
+import Control.Monad.Except (MonadError(..))
+import Control.Monad.Trans.Except (ExceptT, runExceptT)
+
 runErrT :: ExceptT e m a -> m (Either e a)
 runErrT = runExceptT
 type ErrT = ExceptT
-#else
-import Control.Monad.Error
-runErrT :: ErrorT e m a -> m (Either e a)
-runErrT = runErrorT
-type ErrT = ErrorT
-#endif
-
diff --git a/Network/TLS/Handshake/Certificate.hs b/Network/TLS/Handshake/Certificate.hs
--- a/Network/TLS/Handshake/Certificate.hs
+++ b/Network/TLS/Handshake/Certificate.hs
@@ -16,6 +16,7 @@
 import Network.TLS.Context.Internal
 import Network.TLS.Struct
 import Network.TLS.X509
+import Control.Monad (unless)
 import Control.Monad.State.Strict
 import Control.Exception (SomeException)
 import Data.X509 (ExtKeyUsage(..), ExtKeyUsageFlag, extensionGet)
diff --git a/Network/TLS/Handshake/State.hs b/Network/TLS/Handshake/State.hs
--- a/Network/TLS/Handshake/State.hs
+++ b/Network/TLS/Handshake/State.hs
@@ -2,7 +2,6 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE CPP #-}
 -- |
 -- Module      : Network.TLS.Handshake.State
 -- License     : BSD-style
@@ -190,9 +189,7 @@
 instance MonadState HandshakeState HandshakeM where
     put x = HandshakeM (put x)
     get   = HandshakeM get
-#if MIN_VERSION_mtl(2,1,0)
     state f = HandshakeM (state f)
-#endif
 
 -- create a new empty handshake state
 newEmptyHandshake :: Version -> ClientRandom -> HandshakeState
diff --git a/Network/TLS/Record/State.hs b/Network/TLS/Record/State.hs
--- a/Network/TLS/Record/State.hs
+++ b/Network/TLS/Record/State.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE CPP #-}
 -- |
 -- Module      : Network.TLS.Record.State
 -- License     : BSD-style
@@ -112,9 +111,7 @@
 instance MonadState RecordState RecordM where
     put x = RecordM $ \_  _  -> Right ((), x)
     get   = RecordM $ \_  st -> Right (st, st)
-#if MIN_VERSION_mtl(2,1,0)
     state f = RecordM $ \_ st -> Right (f st)
-#endif
 
 instance MonadError TLSError RecordM where
     throwError e   = RecordM $ \_ _ -> Left e
diff --git a/Network/TLS/State.hs b/Network/TLS/State.hs
--- a/Network/TLS/State.hs
+++ b/Network/TLS/State.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
@@ -108,9 +107,7 @@
 instance MonadState TLSState TLSSt where
     put x = TLSSt (lift $ put x)
     get   = TLSSt (lift get)
-#if MIN_VERSION_mtl(2,1,0)
     state f = TLSSt (lift $ state f)
-#endif
 
 runTLSState :: TLSSt a -> TLSState -> (Either TLSError a, TLSState)
 runTLSState f st = runState (runErrT (runTLSSt f)) st
diff --git a/Network/TLS/Struct.hs b/Network/TLS/Struct.hs
--- a/Network/TLS/Struct.hs
+++ b/Network/TLS/Struct.hs
@@ -9,7 +9,6 @@
 --
 -- the Struct module contains all definitions and values of the TLS protocol
 --
-{-# LANGUAGE CPP #-}
 module Network.TLS.Struct
     ( Version(..)
     , ConnectionEnd(..)
@@ -67,10 +66,6 @@
 import Network.TLS.Crypto
 import Network.TLS.Util.Serialization
 import Network.TLS.Imports
-#if MIN_VERSION_mtl(2,2,1)
-#else
-import Control.Monad.Error
-#endif
 
 data ConnectionEnd = ConnectionServer | ConnectionClient
 data CipherType = CipherStream | CipherBlock | CipherAEAD
@@ -172,13 +167,6 @@
     | Error_Packet_unexpected String String
     | Error_Packet_Parsing String
     deriving (Eq, Show, Typeable)
-
-#if MIN_VERSION_mtl(2,2,1)
-#else
-instance Error TLSError where
-    noMsg  = Error_Misc ""
-    strMsg = Error_Misc
-#endif
 
 instance Exception TLSError
 
diff --git a/tls.cabal b/tls.cabal
--- a/tls.cabal
+++ b/tls.cabal
@@ -1,5 +1,5 @@
 Name:                tls
-Version:             1.5.7
+Version:             1.5.8
 Description:
    Native Haskell TLS and SSL protocol implementation for server and client.
    .
@@ -42,7 +42,7 @@
 Library
   Default-Language:  Haskell2010
   Build-Depends:     base >= 4.9 && < 5
-                   , mtl >= 2
+                   , mtl >= 2.2.1
                    , transformers
                    , cereal >= 0.5.3
                    , bytestring
