diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,7 @@
+0.0.4.0
+
+* switch to errors-2.0
+* workaround for parse error on inline image in content stream
 
 0.0.3.3
 
diff --git a/lib/Pdf/Toolbox/Content/FontInfo.hs b/lib/Pdf/Toolbox/Content/FontInfo.hs
--- a/lib/Pdf/Toolbox/Content/FontInfo.hs
+++ b/lib/Pdf/Toolbox/Content/FontInfo.hs
@@ -121,7 +121,7 @@
     n <- intValue x
     ws <- forM arr $ \w -> fromObject w >>= realValue
     go res {cidFontWidthsChars = Map.fromList (zip [n ..] ws) `mappend` cidFontWidthsChars res} xs
-  go _ _ = left $ UnexpectedError "Can't parse CIDFont width"
+  go _ _ = throwE $ UnexpectedError "Can't parse CIDFont width"
 
 -- | Get glyph width by glyph code
 cidFontGetWidth :: CIDFontWidths -> Int -> Maybe Double
diff --git a/lib/Pdf/Toolbox/Content/Parser.hs b/lib/Pdf/Toolbox/Content/Parser.hs
--- a/lib/Pdf/Toolbox/Content/Parser.hs
+++ b/lib/Pdf/Toolbox/Content/Parser.hs
@@ -9,6 +9,7 @@
 where
 
 import Data.Int
+import qualified Data.ByteString.Char8 as ByteString8
 import Data.Attoparsec.ByteString.Char8 (Parser)
 import qualified Data.Attoparsec.ByteString.Char8 as Parser
 import Data.IORef
@@ -48,11 +49,11 @@
         `catch` (\e -> return $ Left $ UnexpectedError $ show (e :: Streams.ParseException))
       case e of
         Right expr -> return expr
-        Left er -> left er
+        Left er -> throwE er
     case expr of
       Nothing -> case args of
                    [] -> return Nothing
-                   _ -> left $ UnexpectedError $ "Args without op: " ++ show args
+                   _ -> throwE $ UnexpectedError $ "Args without op: " ++ show args
       Just (Obj o) -> go (o : args)
       Just (Op o) -> return $ Just (o, reverse args)
 
@@ -74,7 +75,7 @@
         case ss of
           [] -> return Nothing
           (h:t) -> do
-            reader <- runEitherT $ mkReader h t
+            reader <- runExceptT $ mkReader h t
             case reader of
               Left e -> liftIO $ ioError $ userError $ show e
               Right r -> do
@@ -87,7 +88,24 @@
   = (skipSpace >> Parser.endOfInput >> return Nothing)
   <|> do
     skipSpace
-    fmap Just $ fmap Obj parseObject <|> fmap (Op . toOp) (Parser.takeWhile1 isRegularChar)
+    fmap Just $ fmap Obj parseObject
+      <|> fmap (Op . toOp) (Parser.takeWhile1 isRegularChar)
+      -- See Note Inline image
+      <|> fmap (Op . UnknownOp . ByteString8.pack . return) Parser.anyChar
+
+{- Note Inline image
+
+There is at least one case that doesn't fit the way we represent content
+stream operators: inline images, see Pdf1.7:8.9.7
+
+Inline image looks like "BI" operator, a number of key/value pairs, "ID"
+operator, image data and "EI" operator. I have no idea how to handle that case.
+There is no data length, so the "EI" string is the only indicator for end
+of image data. What if the data contains "EI"?
+
+For now lets skip all unknown bytes as unknown operator. That seems to work,
+but it is not reliable.
+-}
 
 -- Treat comments as spaces
 skipSpace :: Parser ()
diff --git a/lib/Pdf/Toolbox/Content/Processor.hs b/lib/Pdf/Toolbox/Content/Processor.hs
--- a/lib/Pdf/Toolbox/Content/Processor.hs
+++ b/lib/Pdf/Toolbox/Content/Processor.hs
@@ -100,13 +100,13 @@
 processOp :: Monad m => Operator -> Processor -> PdfE m Processor
 
 processOp (Op_q, []) p = return p {prStateStack = prState p : prStateStack p}
-processOp (Op_q, args) _ = left $ UnexpectedError $ "Op_q: wrong number of arguments: " ++ show args
+processOp (Op_q, args) _ = throwE $ UnexpectedError $ "Op_q: wrong number of arguments: " ++ show args
 
 processOp (Op_Q, []) p =
   case prStateStack p of
-    [] -> left $ UnexpectedError "Op_Q: state is empty"
+    [] -> throwE $ UnexpectedError "Op_Q: state is empty"
     (x:xs) -> return p {prState = x, prStateStack = xs}
-processOp (Op_Q, args) _ = left $ UnexpectedError $ "Op_Q: wrong number of arguments: " ++ show args
+processOp (Op_Q, args) _ = throwE $ UnexpectedError $ "Op_Q: wrong number of arguments: " ++ show args
 
 processOp (Op_BT, []) p = do
   ensureInTextObject False p
@@ -116,7 +116,7 @@
     gsTextMatrix = identity,
     gsTextLineMatrix = identity
     }}
-processOp (Op_BT, args) _ = left $ UnexpectedError $ "Op_BT: wrong number of arguments: " ++ show args
+processOp (Op_BT, args) _ = throwE $ UnexpectedError $ "Op_BT: wrong number of arguments: " ++ show args
 
 processOp (Op_ET, []) p = do
   ensureInTextObject True p
@@ -124,7 +124,7 @@
   return p {prState = gstate {
     gsInText = False
     }}
-processOp (Op_ET, args) _ = left $ UnexpectedError $ "Op_ET: wrong number of arguments: " ++ show args
+processOp (Op_ET, args) _ = throwE $ UnexpectedError $ "Op_ET: wrong number of arguments: " ++ show args
 
 processOp (Op_Td, [txo, tyo]) p = do
   ensureInTextObject True p
@@ -136,13 +136,13 @@
     gsTextMatrix = tm,
     gsTextLineMatrix = tm
     }}
-processOp (Op_Td, args) _ = left $ UnexpectedError $ "Op_Td: wrong number of arguments: " ++ show args
+processOp (Op_Td, args) _ = throwE $ UnexpectedError $ "Op_Td: wrong number of arguments: " ++ show args
 
 processOp (Op_TD, [txo, tyo]) p = do
   l <- fromObject tyo >>= realValue
   p' <- processOp (Op_TL, [ONumber $ NumReal $ negate l]) p
   processOp (Op_Td, [txo, tyo]) p'
-processOp (Op_TD, args) _ = left $ UnexpectedError $ "Op_TD: wrong number of arguments: " ++ show args
+processOp (Op_TD, args) _ = throwE $ UnexpectedError $ "Op_TD: wrong number of arguments: " ++ show args
 
 processOp (Op_Tm, [a', b', c', d', e', f']) p = do
   ensureInTextObject True p
@@ -158,14 +158,14 @@
     gsTextMatrix = tm,
     gsTextLineMatrix = tm
     }}
-processOp (Op_Tm, args) _ = left $ UnexpectedError $ "Op_Tm: wrong number of arguments: " ++ show args
+processOp (Op_Tm, args) _ = throwE $ UnexpectedError $ "Op_Tm: wrong number of arguments: " ++ show args
 
 processOp (Op_T_star, []) p = do
   ensureInTextObject True p
   let gstate = prState p
       l = gsTextLeading gstate
   processOp (Op_TD, map (ONumber . NumReal) [0, negate l]) p
-processOp (Op_T_star, args) _ = left $ UnexpectedError $ "Op_T_star: wrong number of arguments: " ++ show args
+processOp (Op_T_star, args) _ = throwE $ UnexpectedError $ "Op_T_star: wrong number of arguments: " ++ show args
 
 processOp (Op_TL, [lo]) p = do
   l <- fromObject lo >>= realValue
@@ -173,7 +173,7 @@
   return p {prState = gstate {
     gsTextLeading = l
     }}
-processOp (Op_TL, args) _ = left $ UnexpectedError $ "Op_TL: wrong number of arguments: " ++ show args
+processOp (Op_TL, args) _ = throwE $ UnexpectedError $ "Op_TL: wrong number of arguments: " ++ show args
 
 processOp (Op_cm, [a', b', c', d', e', f']) p = do
   a <- fromObject a' >>= realValue
@@ -187,7 +187,7 @@
   return p {prState = gstate {
     gsCurrentTransformMatrix = ctm
     }}
-processOp (Op_cm, args) _ = left $ UnexpectedError $ "Op_cm: wrong number of arguments: " ++ show args
+processOp (Op_cm, args) _ = throwE $ UnexpectedError $ "Op_cm: wrong number of arguments: " ++ show args
 
 processOp (Op_Tf, [fontO, szO]) p = do
   font <- fromObject fontO
@@ -197,17 +197,17 @@
     gsFont = Just font,
     gsFontSize = Just sz
     }}
-processOp (Op_Tf, args) _ = left $ UnexpectedError $ "Op_Tf: wrong number of agruments: " ++ show args
+processOp (Op_Tf, args) _ = throwE $ UnexpectedError $ "Op_Tf: wrong number of agruments: " ++ show args
 
 processOp (Op_Tj, [OStr str]) p = do
   let gstate = prState p
   fontName <-
     case gsFont gstate of
-      Nothing -> left $ UnexpectedError "Op_Tj: font not set"
+      Nothing -> throwE $ UnexpectedError "Op_Tj: font not set"
       Just fn -> return fn
   fontSize <-
     case gsFontSize gstate of
-      Nothing -> left $ UnexpectedError "Op_Tj: font size not set"
+      Nothing -> throwE $ UnexpectedError "Op_Tj: font size not set"
       Just fs -> return fs
   let (tm, glyphs) = positionGlyghs fontSize (gsCurrentTransformMatrix gstate)
                        (gsTextMatrix gstate) (gsTextCharSpacing gstate) (gsTextWordSpacing gstate) $
@@ -218,17 +218,17 @@
       gsTextMatrix = tm
       }
     }
-processOp (Op_Tj, args) _ = left $ UnexpectedError $ "Op_Tj: wrong number of agruments:" ++ show args
+processOp (Op_Tj, args) _ = throwE $ UnexpectedError $ "Op_Tj: wrong number of agruments:" ++ show args
 
 processOp (Op_TJ, [OArray (Array array)]) p = do
   let gstate = prState p
   fontName <-
     case gsFont gstate of
-      Nothing -> left $ UnexpectedError "Op_Tj: font not set"
+      Nothing -> throwE $ UnexpectedError "Op_Tj: font not set"
       Just fn -> return fn
   fontSize <-
     case gsFontSize gstate of
-      Nothing -> left $ UnexpectedError "Op_Tj: font size not set"
+      Nothing -> throwE $ UnexpectedError "Op_Tj: font size not set"
       Just fs -> return fs
   let (textMatrix, glyphs) = loop (gsTextMatrix gstate) [] array
         where
@@ -246,7 +246,7 @@
       gsTextMatrix = textMatrix
       }
     }
-processOp (Op_TJ, args) _ = left $ UnexpectedError $ "Op_TJ: wrong number of agruments:" ++ show args
+processOp (Op_TJ, args) _ = throwE $ UnexpectedError $ "Op_TJ: wrong number of agruments:" ++ show args
 
 processOp (Op_Tc, [o]) p = do
   spacing <- fromObject o >>= realValue
@@ -256,7 +256,7 @@
       gsTextCharSpacing = spacing
       }
     }
-processOp (Op_Tc, args) _ = left $ UnexpectedError $ "Op_Tc: wrong number of agruments:" ++ show args
+processOp (Op_Tc, args) _ = throwE $ UnexpectedError $ "Op_Tc: wrong number of agruments:" ++ show args
 
 processOp (Op_Tw, [o]) p = do
   spacing <- fromObject o >>= realValue
@@ -266,18 +266,18 @@
       gsTextWordSpacing = spacing
       }
     }
-processOp (Op_Tw, args) _ = left $ UnexpectedError $ "Op_Tw: wrong number of agruments:" ++ show args
+processOp (Op_Tw, args) _ = throwE $ UnexpectedError $ "Op_Tw: wrong number of agruments:" ++ show args
 
 processOp (Op_apostrophe, [o]) p = do
   p' <- processOp (Op_T_star, []) p
   processOp (Op_Tj, [o]) p'
-processOp (Op_apostrophe, args) _ = left $ UnexpectedError $ "Op_apostrophe: wrong number of agruments:" ++ show args
+processOp (Op_apostrophe, args) _ = throwE $ UnexpectedError $ "Op_apostrophe: wrong number of agruments:" ++ show args
 
 processOp _ p = return p
 
 ensureInTextObject :: Monad m => Bool -> Processor -> PdfE m ()
 ensureInTextObject inText p =
-  unless (inText == gsInText (prState p)) $ left $
+  unless (inText == gsInText (prState p)) $ throwE $
     UnexpectedError $ "ensureInTextObject: expected: " ++ show inText ++ ", found: " ++ show (gsInText $ prState p)
 
 positionGlyghs :: Double -> Transform Double -> Transform Double -> Double -> Double -> [(Glyph, Double)] -> (Transform Double, [Glyph])
diff --git a/pdf-toolbox-content.cabal b/pdf-toolbox-content.cabal
--- a/pdf-toolbox-content.cabal
+++ b/pdf-toolbox-content.cabal
@@ -1,5 +1,5 @@
 name:                pdf-toolbox-content
-version:             0.0.3.3
+version:             0.0.4.0
 synopsis:            A collection of tools for processing PDF files
 license:             BSD3
 license-file:        LICENSE
@@ -41,4 +41,4 @@
                        base16-bytestring,
                        text,
                        io-streams,
-                       pdf-toolbox-core >=0.0.2.0 && <0.0.4
+                       pdf-toolbox-core ==0.0.4.*
