diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,9 @@
+## 1.2.18
+
+### Other Changes
+
+* Switch from `either` to `errors`.
+
 ## 1.2.17
 
 ### Other Changes
diff --git a/engine-io.cabal b/engine-io.cabal
--- a/engine-io.cabal
+++ b/engine-io.cabal
@@ -1,5 +1,5 @@
 name: engine-io
-version: 1.2.17
+version: 1.2.18
 synopsis: A Haskell implementation of Engine.IO
 homepage: http://github.com/ocharles/engine.io
 license: BSD3
@@ -33,7 +33,7 @@
     base >=4.6 && <4.11,
     base64-bytestring >=1.0 && <1.1,
     bytestring >=0.10.2.0 && <0.11,
-    either >= 3.4 && <4.5,
+    errors >= 2.0.0 && <2.3,
     free >= 4.9 && <5.0,
     monad-loops >=0.4 && <0.5,
     mwc-random >=0.13 && <0.14,
diff --git a/src/Network/EngineIO.hs b/src/Network/EngineIO.hs
--- a/src/Network/EngineIO.hs
+++ b/src/Network/EngineIO.hs
@@ -52,13 +52,13 @@
 import Control.Applicative
 import Control.Concurrent (threadDelay)
 import Control.Concurrent.MVar (MVar, newMVar, withMVar)
+import Control.Error (exceptT, throwE)
 import Control.Exception (SomeException(SomeException), try)
 import Control.Monad (MonadPlus, forever, guard, mzero, replicateM, when)
-import Control.Monad.Trans.Iter (cutoff, delay, retract)
 import Control.Monad.IO.Class (MonadIO, liftIO)
 import Control.Monad.Loops (unfoldM)
 import Control.Monad.Trans.Class (lift)
-import Control.Monad.Trans.Either (eitherT, left)
+import Control.Monad.Trans.Iter (cutoff, delay, retract)
 import Control.Monad.Trans.Maybe (runMaybeT)
 import Data.Aeson ((.=))
 import Data.Char (digitToInt, intToDigit)
@@ -410,8 +410,8 @@
 handler :: MonadIO m => EngineIO -> (Socket -> m SocketApp) -> ServerAPI m -> m ()
 handler eio socketHandler api@ServerAPI{..} = do
   queryParams <- srvGetQueryParams
-  eitherT (serveError api) return $ do
-    reqTransport <- maybe (left TransportUnknown) return $ do
+  exceptT (serveError api) return $ do
+    reqTransport <- maybe (throwE TransportUnknown) return $ do
       [t] <- HashMap.lookup "transport" queryParams
       parseTransportType (Text.decodeUtf8 t)
 
@@ -419,11 +419,11 @@
       for (HashMap.lookup "sid" queryParams) $ \sids -> do
         sid <- case sids of
                  [sid] -> return sid
-                 _ -> left SessionIdUnknown
+                 _ -> throwE SessionIdUnknown
 
         mSocket <- liftIO (STM.atomically (HashMap.lookup sid <$> getOpenSockets eio))
         case mSocket of
-          Nothing -> left SessionIdUnknown
+          Nothing -> throwE SessionIdUnknown
           Just s -> return s
 
     supportsBinary <-
@@ -431,7 +431,7 @@
         Just ["1"] -> return False
         Just ["0"] -> return True
         Nothing    -> return True
-        _          -> left BadRequest
+        _          -> throwE BadRequest
 
     case socket of
       Just s -> do
@@ -441,7 +441,7 @@
             | reqTransport == Polling -> lift (handlePoll api transport supportsBinary)
             | reqTransport == Websocket -> lift (upgrade api s)
 
-          _ -> left BadRequest
+          _ -> throwE BadRequest
 
       Nothing ->
         lift (freshSession eio socketHandler api supportsBinary)
