diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,6 @@
+0.0.4.0
+
+* switch to errors-2.0
 
 0.0.3.3
 
diff --git a/lib/Pdf/Toolbox/Core/Error.hs b/lib/Pdf/Toolbox/Core/Error.hs
--- a/lib/Pdf/Toolbox/Core/Error.hs
+++ b/lib/Pdf/Toolbox/Core/Error.hs
@@ -29,7 +29,7 @@
   deriving Show
 
 -- | API uses this for error handling
-type PdfE m = EitherT PdfError m
+type PdfE m = ExceptT PdfError m
 
 -- | Wrap any 'PdfError' into 'AnnotatedError'
 --
@@ -51,4 +51,4 @@
       `catch` (\(e :: IOError) -> return $ Left $ IOError e)
   case res of
     Right a -> return a
-    Left e -> left e
+    Left e -> throwE e
diff --git a/lib/Pdf/Toolbox/Core/IO.hs b/lib/Pdf/Toolbox/Core/IO.hs
--- a/lib/Pdf/Toolbox/Core/IO.hs
+++ b/lib/Pdf/Toolbox/Core/IO.hs
@@ -52,7 +52,7 @@
     `catch` (\(Streams.ParseException str) -> return $ Left $ ParseError [] str)
     `catch` (\(e :: IOError) -> return $ Left $ IOError e)
   case res of
-    Left e -> left e
+    Left e -> throwE e
     Right r -> return r
 
 -- | Convert random access stream to sequential
diff --git a/lib/Pdf/Toolbox/Core/Object/Util.hs b/lib/Pdf/Toolbox/Core/Object/Util.hs
--- a/lib/Pdf/Toolbox/Core/Object/Util.hs
+++ b/lib/Pdf/Toolbox/Core/Object/Util.hs
@@ -31,8 +31,8 @@
 lookupDict :: Monad m => Name -> Dict -> PdfE m (Object ())
 lookupDict key (Dict d) =
   case lookup key d of
-    Just o -> right o
-    Nothing -> left $ UnexpectedError $ "Key not found: " ++ show key ++ " " ++ show d
+    Just o -> return o
+    Nothing -> throwE $ UnexpectedError $ "Key not found: " ++ show key ++ " " ++ show d
 
 lookupDict' :: Name -> Dict -> Maybe (Object ())
 lookupDict' key (Dict d) = lookup key d
@@ -51,44 +51,44 @@
   Dict vals = deleteValueForKey key dict
 
 intValue :: Monad m => Number -> PdfE m Int
-intValue (NumInt i) = right i
-intValue (NumReal r) = left $ UnexpectedError $ "Integer expected, but real received: " ++ show r
+intValue (NumInt i) = return i
+intValue (NumReal r) = throwE $ UnexpectedError $ "Integer expected, but real received: " ++ show r
 
 realValue :: Monad m => Number -> PdfE m Double
-realValue (NumReal r) = right r
-realValue (NumInt i) = right $ fromIntegral i
+realValue (NumReal r) = return r
+realValue (NumInt i) = return $ fromIntegral i
 
 toNumber :: (Show a, Monad m) => Object a -> PdfE m Number
-toNumber (ONumber n) = right n
-toNumber o = left $ UnexpectedError $ "Can't cast object to Number: " ++ show o
+toNumber (ONumber n) = return n
+toNumber o = throwE $ UnexpectedError $ "Can't cast object to Number: " ++ show o
 
 toBoolean :: (Show a, Monad m) => Object a -> PdfE m Boolean
-toBoolean (OBoolean b) = right b
-toBoolean o = left $ UnexpectedError $ "Can't cast object to Boolean: " ++ show o
+toBoolean (OBoolean b) = return b
+toBoolean o = throwE $ UnexpectedError $ "Can't cast object to Boolean: " ++ show o
 
 toName :: (Show a, Monad m) => Object a -> PdfE m Name
-toName (OName n) = right n
-toName o = left $ UnexpectedError $ "Can't cast object to Name: " ++ show o
+toName (OName n) = return n
+toName o = throwE $ UnexpectedError $ "Can't cast object to Name: " ++ show o
 
 toDict :: (Show a, Monad m) => Object a -> PdfE m Dict
-toDict (ODict d) = right d
-toDict o = left $ UnexpectedError $ "Can't cast object to Dict: " ++ show o
+toDict (ODict d) = return d
+toDict o = throwE $ UnexpectedError $ "Can't cast object to Dict: " ++ show o
 
 toStr :: (Show a, Monad m) => Object a -> PdfE m Str
-toStr (OStr s) = right s
-toStr o = left $ UnexpectedError $ "Can't cast object to Str: " ++ show o
+toStr (OStr s) = return s
+toStr o = throwE $ UnexpectedError $ "Can't cast object to Str: " ++ show o
 
 toRef :: (Show a, Monad m) => Object a -> PdfE m Ref
-toRef (ORef r) = right r
-toRef o = left $ UnexpectedError $ "Can't cast object to Ref: " ++ show o
+toRef (ORef r) = return r
+toRef o = throwE $ UnexpectedError $ "Can't cast object to Ref: " ++ show o
 
 toArray :: (Show a, Monad m) => Object a -> PdfE m Array
-toArray (OArray a) = right a
-toArray o = left $ UnexpectedError $ "Can't cast object to Array: " ++ show o
+toArray (OArray a) = return a
+toArray o = throwE $ UnexpectedError $ "Can't cast object to Array: " ++ show o
 
 toStream :: (Show a, Monad m) => Object a -> PdfE m (Stream a)
-toStream (OStream s) = right s
-toStream o = left $ UnexpectedError $ "Can't cast object to Stream: " ++ show o
+toStream (OStream s) = return s
+toStream o = throwE $ UnexpectedError $ "Can't cast object to Stream: " ++ show o
 
 -- | Apply function to all stream contents
 mapObject :: (a -> b) -> Object a -> Object b
diff --git a/lib/Pdf/Toolbox/Core/Stream.hs b/lib/Pdf/Toolbox/Core/Stream.hs
--- a/lib/Pdf/Toolbox/Core/Stream.hs
+++ b/lib/Pdf/Toolbox/Core/Stream.hs
@@ -86,10 +86,10 @@
 
 buildFilterList :: Monad m => Dict -> PdfE m [(Name, Maybe Dict)]
 buildFilterList dict = do
-  f <- lookupDict "Filter" dict `catchT` (const $ right ONull)
-  p <- lookupDict "DecodeParms" dict `catchT` (const $ right ONull)
+  f <- lookupDict "Filter" dict `catchE` (const $ return ONull)
+  p <- lookupDict "DecodeParms" dict `catchE` (const $ return ONull)
   case (f, p) of
-    (ONull, _) -> right []
+    (ONull, _) -> return []
     (OName fd, ONull) -> return [(fd, Nothing)]
     (OName fd, ODict pd) -> return [(fd, Just pd)]
     (OName fd, OArray (Array [ODict pd])) -> return [(fd, Just pd)]
@@ -100,4 +100,4 @@
       fa' <- mapM fromObject fa
       pa' <- mapM fromObject pa
       return $ zip fa' (map Just pa')
-    _ -> left $ UnexpectedError $ "Can't handle Filter and DecodeParams: (" ++ show f ++ ", " ++ show p ++ ")"
+    _ -> throwE $ UnexpectedError $ "Can't handle Filter and DecodeParams: (" ++ show f ++ ", " ++ show p ++ ")"
diff --git a/lib/Pdf/Toolbox/Core/Stream/Filter/FlateDecode.hs b/lib/Pdf/Toolbox/Core/Stream/Filter/FlateDecode.hs
--- a/lib/Pdf/Toolbox/Core/Stream/Filter/FlateDecode.hs
+++ b/lib/Pdf/Toolbox/Core/Stream/Filter/FlateDecode.hs
@@ -37,11 +37,11 @@
 decode :: Maybe Dict -> IS -> IO IS
 decode Nothing is = Streams.decompress is
 decode (Just dict) is = do
-  predictor <- runEitherT $ lookupDict "Predictor" dict
+  predictor <- runExceptT $ lookupDict "Predictor" dict
   case predictor of
     Left _ -> Streams.decompress is
     Right p -> do
-      p' <- runEitherT $ fromObject p >>= intValue
+      p' <- runExceptT $ fromObject p >>= intValue
       case p' of
         Left e -> fail $ "Malformed predictor: " ++ show e
         Right val -> Streams.decompress is >>= unpredict dict val
@@ -49,7 +49,7 @@
 unpredict :: Dict -> Int -> IS -> IO IS
 unpredict _ 1 is = return is
 unpredict dict 12 is = do
-  c <- runEitherT $ lookupDict "Columns" dict >>= fromObject >>= intValue
+  c <- runExceptT $ lookupDict "Columns" dict >>= fromObject >>= intValue
   case c of
     Left e -> fail $ "flateDecode: malformed Columns value: " ++ show e
     Right cols -> unpredict12 (cols + 1) is
diff --git a/lib/Pdf/Toolbox/Core/Util.hs b/lib/Pdf/Toolbox/Core/Util.hs
--- a/lib/Pdf/Toolbox/Core/Util.hs
+++ b/lib/Pdf/Toolbox/Core/Util.hs
@@ -27,7 +27,7 @@
 readObjectAtOffset ris off gen = do
   seek ris off
   (Ref _ gen', o) <- inputStream ris >>= parse parseIndirectObject
-  unless (gen == gen') $ left $ UnexpectedError $ "Generation mismatch, expected: " ++ show gen ++ ", found: " ++ show gen'
+  unless (gen == gen') $ throwE $ UnexpectedError $ "Generation mismatch, expected: " ++ show gen ++ ", found: " ++ show gen'
   case o of
     ONumber val -> return $ ONumber val
     OBoolean val -> return $ OBoolean val
@@ -36,7 +36,7 @@
     OArray val -> return $ OArray val
     OStr val -> return $ OStr val
     OStream (Stream dict _) -> (OStream . Stream dict) `liftM` tell ris
-    ORef _ -> left $ UnexpectedError "Indirect object can't be ORef"
+    ORef _ -> throwE $ UnexpectedError "Indirect object can't be ORef"
     ONull -> return ONull
 
 -- | Read object from object stream
diff --git a/lib/Pdf/Toolbox/Core/XRef.hs b/lib/Pdf/Toolbox/Core/XRef.hs
--- a/lib/Pdf/Toolbox/Core/XRef.hs
+++ b/lib/Pdf/Toolbox/Core/XRef.hs
@@ -79,7 +79,7 @@
 -- The keyword iyself is consumed
 isTable :: MonadIO m => IS -> PdfE m Bool
 isTable is = do
-  res <- runEitherT (parse tableXRef is)
+  res <- runExceptT (parse tableXRef is)
   case res of
     Right _ -> return True
     Left _ -> return False
@@ -88,7 +88,7 @@
 prevXRef :: MonadIO m => RIS -> XRef -> PdfE m (Maybe XRef)
 prevXRef ris xref = annotateError "Can't find prev xref" $ do
   tr <- trailer ris xref
-  prev <- runEitherT $ lookupDict "Prev" tr
+  prev <- runExceptT $ lookupDict "Prev" tr
   case prev of
     Right p -> do
       off <- fromObject p >>= intValue
@@ -117,7 +117,7 @@
 nextSubsectionHeader :: MonadIO m => IS -> Int -> PdfE m (Maybe (Int, Int))
 nextSubsectionHeader is count = do
   skipSubsection is count
-  hush `liftM` (runEitherT $ subsectionHeader is)
+  hush `liftM` (runExceptT $ subsectionHeader is)
 
 skipSubsection :: MonadIO m => IS -> Int -> PdfE m ()
 skipSubsection is count = dropExactly (count * 20) is
@@ -138,7 +138,7 @@
       then do
         tell ris >>= seek ris . (+ (fromIntegral $ index - start) * 20)
         (off, gen', free) <- inputStream ris >>= parse parseTableEntry
-        unless (gen == gen') $ left $ UnexpectedError "Generation mismatch"
+        unless (gen == gen') $ throwE $ UnexpectedError "Generation mismatch"
         return $ Just $ TableEntry off gen free
       else do
         is <- inputStream ris
@@ -156,20 +156,20 @@
 
   index <- do
     Array i <- (lookupDict "Index" dict >>= fromObject)
-      `catchT`
+      `catchE`
       const (return $ Array [ONumber $ NumInt 0, ONumber $ NumInt sz])
     let convertIndex res [] = return $ reverse res
         convertIndex res (x1:x2:xs) = do
           from <- fromObject x1 >>= intValue
           count <- fromObject x2 >>= intValue
           convertIndex ((from, count) : res) xs
-        convertIndex _ _ = left $ UnexpectedError $ "Malformed Index in xref stream: " ++ show i
+        convertIndex _ _ = throwE $ UnexpectedError $ "Malformed Index in xref stream: " ++ show i
     convertIndex [] i
 
   width <- do
     Array w <- lookupDict "W" dict >>= fromObject
     mapM (fromObject >=> intValue) w
-  unless (length width == 3) $ left $ UnexpectedError $ "Malformed With array in xref stream: " ++ show width
+  unless (length width == 3) $ throwE $ UnexpectedError $ "Malformed With array in xref stream: " ++ show width
 
   values <- do
     let position = loop 0 index
@@ -198,4 +198,4 @@
         0 -> return $ Just $ StreamEntryFree (fromIntegral v2) (fromIntegral v3)
         1 -> return $ Just $ StreamEntryUsed v2 (fromIntegral v3)
         2 -> return $ Just $ StreamEntryCompressed (fromIntegral v2) (fromIntegral v3)
-        _ -> left $ UnexpectedError $ "Unexpected xret stream entry type: " ++ show v1
+        _ -> throwE $ UnexpectedError $ "Unexpected xret stream entry type: " ++ show v1
diff --git a/pdf-toolbox-core.cabal b/pdf-toolbox-core.cabal
--- a/pdf-toolbox-core.cabal
+++ b/pdf-toolbox-core.cabal
@@ -1,5 +1,5 @@
 name:                pdf-toolbox-core
-version:             0.0.3.3
+version:             0.0.4.0
 synopsis:            A collection of tools for processing PDF files.
 license:             BSD3
 license-file:        LICENSE
@@ -53,7 +53,7 @@
                        io-streams,
                        attoparsec >= 0.10,
                        scientific,
-                       errors < 2.0,
+                       errors >=2.0 && <3.0,
                        transformers,
                        containers,
                        zlib-bindings
