diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+# 2.2.0
+
+* BREAKING CHANGE: Use `Text` instead of `String`
+* Add `handleExceptT`
+
+# 2.1.3
+
+* Support older versions of `ghc`
+
+# 2.1.2
+
+* Increase upper bound on `transformers` dependency
+
 # 2.1.1
 
 * Increase upper bound on `transformers-compat`
diff --git a/Control/Error.hs b/Control/Error.hs
--- a/Control/Error.hs
+++ b/Control/Error.hs
@@ -10,7 +10,7 @@
       'EitherT', and 'MonadPlus' variations on total functions
 
     * "Control.Error.Script": Support for simple scripts that catch all errors
-      and transform them to 'String's
+      and transform them to 'Text'
 
     * "Control.Error.Util": Utility functions and conversions between common
       error-handling types
diff --git a/Control/Error/Script.hs b/Control/Error/Script.hs
--- a/Control/Error/Script.hs
+++ b/Control/Error/Script.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE OverloadedStrings #-}
+
 {-|
-    Use this module if you like to write simple scripts with 'String'-based
+    Use this module if you like to write simple scripts with 'Text'-based
     errors, but you prefer to use 'ExceptT' to handle errors rather than
     @Control.Exception@.
 
@@ -24,6 +26,8 @@
 import Control.Monad.Trans.Except (ExceptT(ExceptT), runExceptT)
 import Control.Error.Util (errLn)
 import Data.EitherR (fmapL)
+import Data.Monoid ((<>))
+import Data.Text (Text)
 import System.Environment (getProgName)
 import System.Exit (exitFailure)
 
@@ -31,9 +35,11 @@
 import Control.Monad.Trans.Class (lift)
 import System.IO (stderr)
 
--- | An 'IO' action that can fail with a 'String' error message
-type Script = ExceptT String IO
+import qualified Data.Text
 
+-- | An 'IO' action that can fail with a 'Text' error message
+type Script = ExceptT Text IO
+
 {-| Runs the 'Script' monad
 
     Prints the first error to 'stderr' and exits with 'exitFailure'
@@ -43,17 +49,18 @@
     e <- runExceptT s
     case e of
         Left  e -> do
-            errLn =<< liftM (++ ": " ++ e) getProgName
+            let adapt str = Data.Text.pack str <> ": " <> e
+            errLn =<< liftM adapt getProgName
             exitFailure
         Right a -> return a
 
 {-| 'scriptIO' resembles 'lift', except it catches all exceptions and converts
-    them to 'String's.
+    them to 'Text'
 
     Note that 'scriptIO' is compatible with the 'Script' monad.
 -}
-scriptIO :: (MonadIO m) => IO a -> ExceptT String m a
+scriptIO :: (MonadIO m) => IO a -> ExceptT Text m a
 scriptIO = ExceptT
          . liftIO
-         . liftM (fmapL show)
+         . liftM (fmapL (Data.Text.pack . show))
          . (try :: IO a -> IO (Either SomeException a))
diff --git a/Control/Error/Util.hs b/Control/Error/Util.hs
--- a/Control/Error/Util.hs
+++ b/Control/Error/Util.hs
@@ -47,23 +47,27 @@
 
     -- * Exceptions
     tryIO,
+    handleExceptT,
     syncIO
     ) where
 
 import Control.Applicative (Applicative, pure, (<$>))
-import Control.Exception (Handler(..), IOException, SomeException)
+import Control.Exception (Handler(..), IOException, SomeException, Exception)
 import Control.Monad (liftM)
+import Control.Monad.Catch (MonadCatch, try)
 import Control.Monad.IO.Class (MonadIO(liftIO))
-import Control.Monad.Trans.Except (ExceptT(ExceptT), runExceptT)
+import Control.Monad.Trans.Except (ExceptT(ExceptT), runExceptT, withExceptT)
 import Control.Monad.Trans.Maybe (MaybeT(MaybeT), runMaybeT)
 import Data.Dynamic (Dynamic)
 import Data.Monoid (Monoid(mempty, mappend))
 import Data.Maybe (fromMaybe)
+import Data.Text (Text)
 import System.Exit (ExitCode)
 import System.IO (hPutStr, hPutStrLn, stderr)
 import UnexceptionalIO (UIO, Unexceptional)
 
 import qualified Control.Exception as Exception
+import qualified Data.Text.IO
 import qualified UnexceptionalIO   as UIO
 
 -- | Fold an 'ExceptT' by providing one continuation for each constructor
@@ -228,16 +232,21 @@
 fmapRT = liftM
 
 -- | Write a string to standard error
-err :: String -> IO ()
-err = hPutStr stderr
+err :: Text -> IO ()
+err = Data.Text.IO.hPutStr stderr
 
 -- | Write a string with a newline to standard error
-errLn :: String -> IO ()
-errLn = hPutStrLn stderr
+errLn :: Text -> IO ()
+errLn = Data.Text.IO.hPutStrLn stderr
 
 -- | Catch 'IOException's and convert them to the 'ExceptT' monad
 tryIO :: MonadIO m => IO a -> ExceptT IOException m a
 tryIO = ExceptT . liftIO . Exception.try
+
+-- | Run a monad action which may throw an exception in the `ExceptT` monad
+handleExceptT :: (Exception e, Functor m, MonadCatch m) => (e -> x) -> m a -> ExceptT x m a
+handleExceptT handler = bimapExceptT handler id . ExceptT . try
+
 
 {-| Catch all exceptions, except for asynchronous exceptions found in @base@
     and convert them to the 'ExceptT' monad
diff --git a/Data/EitherR.hs b/Data/EitherR.hs
--- a/Data/EitherR.hs
+++ b/Data/EitherR.hs
@@ -173,7 +173,7 @@
 succeedT :: (Monad m) => r -> ExceptRT r m e
 succeedT r = ExceptRT (return r)
 
--- | 'catchT' with the arguments flipped
+-- | 'catchE' with the arguments flipped
 handleE :: (Monad m) => (a -> ExceptT b m r) -> ExceptT a m r -> ExceptT b m r
 handleE = flip catchE
 
diff --git a/errors.cabal b/errors.cabal
--- a/errors.cabal
+++ b/errors.cabal
@@ -1,5 +1,5 @@
 Name: errors
-Version: 2.1.3
+Version: 2.2.0
 Cabal-Version: >=1.8.0.2
 Build-Type: Simple
 Tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.2, GHC == 8.0.1
@@ -25,6 +25,8 @@
 Library
     Build-Depends:
         base                >= 4     && < 5  ,
+        exceptions          >= 0.6   && < 0.9,
+        text                            < 1.3,
         transformers        >= 0.2   && < 0.6,
         transformers-compat >= 0.4   && < 0.6,
         unexceptionalio     >= 0.3   && < 0.4
