diff --git a/bookhound.cabal b/bookhound.cabal
--- a/bookhound.cabal
+++ b/bookhound.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           bookhound
-version:        0.1.17.0
+version:        0.1.18.0
 synopsis:       Simple Parser Combinators
 description:    Please see the README on GitHub at <https://github.com/albertprz/bookhound#readme>
 category:       Parser Combinators
diff --git a/src/Bookhound/Parser.hs b/src/Bookhound/Parser.hs
--- a/src/Bookhound/Parser.hs
+++ b/src/Bookhound/Parser.hs
@@ -1,12 +1,13 @@
 module Bookhound.Parser (Parser, ParseResult, ParseError(..), runParser, errorParser,
                andThen, exactly, isMatch, check, anyOf, allOf, char,
-               withTransform, withError, except) where
+               withTransform, withError, withErrorN, withErrorFrom, except) where
 
-import Bookhound.Utils.Foldable (findJust)
-import Control.Applicative      (liftA2)
-import Data.Either              (fromRight)
-import Data.Maybe               (fromMaybe)
-import Data.Text                (Text, pack, uncons, unpack)
+import           Bookhound.Utils.Foldable (findJust)
+import           Control.Applicative      (liftA2)
+import           Data.Either              (fromRight)
+import           Data.Set                 (Set)
+import qualified Data.Set                 as Set
+import           Data.Text                (Text, pack, uncons, unpack)
 
 type Input = Text
 
@@ -14,7 +15,7 @@
   = P
       { parse     :: Input -> ParseResult a
       , transform :: forall b. Maybe (Parser b -> Parser b)
-      , error     :: Maybe ParseError
+      , errors    :: Set (Int, ParseError)
       }
 
 data ParseResult a
@@ -29,7 +30,7 @@
   | UnexpectedString String
   | NoMatch String
   | ErrorAt String
-  deriving (Eq)
+  deriving (Eq, Ord)
 
 
 instance Show a => Show (ParseResult a) where
@@ -63,25 +64,25 @@
   liftA2 f (P p t e) mb@(P _ t' e') =
     applyTransformsErrors [t, t'] [e, e'] $ mkParser (\x ->
       case p x of
-        Error pe   -> Error $ fromMaybe pe e
         Result i a -> parse ((f a) <$> mb) i
+        Error pe   -> Error pe
     )
 
 instance Monad Parser where
   (>>=) (P p t e) f = applyTransform t $ mkParser (\x ->
       case p x of
-        Error pe   -> Error $ fromMaybe pe e
-        Result i a -> parse (applyError e' p2) i
+        Error pe   -> Error pe
+        Result i a -> parse (applyError (e <> e') p2) i
           where
             p2@(P _ _ e') = f a
     )
 
-runParser :: Parser a -> Input -> Either ParseError a
+runParser :: Parser a -> Input -> Either [ParseError] a
 runParser p@(P _ _ e) i = toEither $ parse (exactly p) i
   where
     toEither = \case
-      Error pe   -> Left $ fromMaybe pe e
       Result _ a -> Right a
+      Error pe   -> Left $ (snd <$> reverse (Set.toList e)) <> [pe]
 
 errorParser :: ParseError -> Parser a
 errorParser = mkParser . const . Error
@@ -105,15 +106,15 @@
     )
 
 anyOf :: [Parser a] -> Parser a
-anyOf ps = anyOfHelper ps Nothing Nothing
+anyOf ps = anyOfHelper ps Nothing mempty
 
 allOf :: [Parser a] -> Parser a
-allOf ps = allOfHelper ps Nothing Nothing
+allOf ps = allOfHelper ps Nothing mempty
 
 
 anyOfHelper :: [Parser a]
             -> (forall b. Maybe (Parser b -> Parser b))
-            -> Maybe ParseError
+            -> Set (Int, ParseError)
             -> Parser a
 anyOfHelper [] _ _  = errorParser $ NoMatch "anyOf"
 anyOfHelper [p] _ _ = p
@@ -129,7 +130,7 @@
 
 allOfHelper :: [Parser a]
             -> (forall b. Maybe (Parser b -> Parser b))
-            -> Maybe ParseError
+            -> Set (Int, ParseError)
             -> Parser a
 allOfHelper [] _ _ = errorParser $ NoMatch "allOf"
 allOfHelper [p] _ _ = p
@@ -166,32 +167,45 @@
   )
 
 withError :: String -> Parser a -> Parser a
-withError = applyError . pure . ErrorAt
+withError = withErrorN 0
 
+withErrorN :: Int -> String -> Parser a -> Parser a
+withErrorN n str = applyError . Set.singleton $ (n, ErrorAt str)
+
+withErrorFrom :: (a -> String) -> Parser a -> Parser a
+withErrorFrom = withErrorNFrom 0
+
+withErrorNFrom :: Int -> (a -> String) -> Parser a -> Parser a
+withErrorNFrom n errFn p =
+  do value <- p
+     withErrorN n (errFn value) $ pure $ value
+
 withTransform :: (forall b. Parser b -> Parser b) -> Parser a -> Parser a
 withTransform t = applyTransform $ Just t
 
 
-applyTransformError :: (forall b. Maybe (Parser b -> Parser b))
-                    -> Maybe ParseError
-                    -> Parser a
-                    -> Parser a
-applyTransformError t e = applyTransform t . applyError e
 
-
 applyTransformsErrors :: (forall b. [Maybe (Parser b -> Parser b)])
-                      -> [Maybe ParseError]
+                      -> [Set (Int, ParseError)]
                       -> Parser a
                       -> Parser a
 applyTransformsErrors ts es =
-  applyTransformError (findJust ts) (findJust es)
+  applyTransformError (findJust ts) (mconcat es)
 
 
+applyTransformError :: (forall b. Maybe (Parser b -> Parser b))
+                    -> Set (Int, ParseError)
+                    -> Parser a
+                    -> Parser a
+applyTransformError t e = applyTransform t . applyError e
+
+
+
 applyTransform :: (forall b. Maybe (Parser b -> Parser b)) -> Parser a -> Parser a
 applyTransform f p =  maybe p (\f' -> (f' p) {transform = f}) f
 
-applyError :: Maybe ParseError -> Parser a -> Parser a
-applyError e p = maybe p (\_ -> p {error = e}) e
+applyError :: Set (Int, ParseError) -> Parser a -> Parser a
+applyError e p@(P _ _ e') = p {errors = e <> e'}
 
 mkParser :: (Input -> ParseResult a) -> Parser a
-mkParser p = P {parse = p, transform = Nothing, error = Nothing}
+mkParser p = P {parse = p, transform = Nothing, errors = Set.empty}
diff --git a/src/Bookhound/Parsers/Collections.hs b/src/Bookhound/Parsers/Collections.hs
--- a/src/Bookhound/Parsers/Collections.hs
+++ b/src/Bookhound/Parsers/Collections.hs
@@ -1,6 +1,6 @@
 module Bookhound.Parsers.Collections (collOf, listOf, tupleOf, mapOf) where
 
-import Bookhound.Parser            (Parser, withError)
+import Bookhound.Parser            (Parser, withErrorN)
 import Bookhound.ParserCombinators (anySepBy, maybeWithin, satisfies)
 import Bookhound.Parsers.Char      (closeCurly, closeParens, closeSquare, comma,
                                     openCurly, openParens, openSquare)
@@ -11,22 +11,25 @@
 
 
 collOf :: Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]
-collOf start end sep elemParser = withError "Collection"
-  $ start *> elemsParser <* end
+collOf start end sep elemParser = withErrorN (-1) "Collection" $
+  start *> elemsParser <* end
   where
     elemsParser = anySepBy sep $ maybeWithin spacing elemParser
 
+
 listOf :: Parser a -> Parser [a]
-listOf = withError "List"
+listOf = withErrorN (-1) "List"
   . collOf openSquare closeSquare comma
 
+
 tupleOf :: Parser a -> Parser [a]
-tupleOf = withError "Tuple"
+tupleOf = withErrorN (-1) "Tuple"
   . satisfies ((>= 2) . length)
   . collOf openParens closeParens comma
 
+
 mapOf :: Ord b => Parser a -> Parser b -> Parser c -> Parser (Map b c)
-mapOf sep p1 p2 = withError "Map"
-  $ Map.fromList <$> collOf openCurly closeCurly comma mapEntry
+mapOf sep p1 p2 = withErrorN (-1) "Map" $
+  Map.fromList <$> collOf openCurly closeCurly comma mapEntry
   where
     mapEntry = (,) <$> p1 <* maybeWithin spacing sep <*> p2
diff --git a/src/Bookhound/Parsers/DateTime.hs b/src/Bookhound/Parsers/DateTime.hs
--- a/src/Bookhound/Parsers/DateTime.hs
+++ b/src/Bookhound/Parsers/DateTime.hs
@@ -1,6 +1,6 @@
 module Bookhound.Parsers.DateTime (date, time, timeZoneOffset, localDateTime, offsetDateTime, dateTime, year, day, month, hour, minute, second) where
 
-import Bookhound.Parser            (Parser, check, withError)
+import Bookhound.Parser            (Parser, check, withErrorN)
 import Bookhound.ParserCombinators (IsMatch (..), within, (<#>), (<|>), (|+),
                                     (|?))
 import Bookhound.Parsers.Char      (colon, dash, digit, plus)
@@ -11,38 +11,41 @@
 
 
 date :: Parser Day
-date = withError "Date"
-  $ fromGregorian <$> year <*> within dash month <*> day
+date = withErrorN (-1) "Date" $
+  fromGregorian <$> year <*> within dash month <*> day
 
 
 time :: Parser TimeOfDay
-time = withError "Time"
-  $ do h <- hour
-       m <- colon *> minute
-       s <- colon *> second
-       decimals <- fromMaybe 0 <$> ((colon *> secondDecimals) |?)
-       pure $ TimeOfDay h m $ read (show s <> "." <> show decimals)
+time = withErrorN (-1) "Time" $
+  do h <- hour
+     m <- colon *> minute
+     s <- colon *> second
+     decimals <- fromMaybe 0 <$> ((colon *> secondDecimals) |?)
+     pure $ TimeOfDay h m $ read (show s <> "." <> show decimals)
 
 
 timeZoneOffset :: Parser TimeZone
-timeZoneOffset = withError "Timezone Offset"
-  $ do pos <- (True <$ plus) <|> (False <$ dash)
-       h <- hour
-       m <- fromMaybe 0 <$> ((colon *> minute) |?)
-       pure $ minutesToTimeZone $ (if pos then 1 else (-1)) * (h * 60 + m)
+timeZoneOffset = withErrorN (-1) "Timezone Offset" $
+  do pos <- (True <$ plus) <|> (False <$ dash)
+     h <- hour
+     m <- fromMaybe 0 <$> ((colon *> minute) |?)
+     pure $ minutesToTimeZone $ (if pos then 1 else (-1)) * (h * 60 + m)
 
+
 localDateTime :: Parser LocalTime
-localDateTime = withError "Local DateTime"
-  $ LocalTime <$> (date <* oneOf ['T', 't']) <*> time
+localDateTime = withErrorN (-1) "Local DateTime" $
+  LocalTime <$> (date <* oneOf ['T', 't']) <*> time
 
+
 offsetDateTime :: Parser ZonedTime
-offsetDateTime = withError "Offset DateTime"
-  $ ZonedTime <$> localDateTime <*> timeZoneOffset
+offsetDateTime = withErrorN (-1) "Offset DateTime" $
+  ZonedTime <$> localDateTime <*> timeZoneOffset
 
+
 dateTime :: Parser ZonedTime
-dateTime = withError "DateTime"
-  $ ((`ZonedTime` minutesToTimeZone 0) <$> localDateTime <* is 'Z') <|>
-            offsetDateTime
+dateTime = withErrorN (-1) "DateTime" $
+  ((`ZonedTime` minutesToTimeZone 0) <$> localDateTime <* is 'Z')
+  <|> offsetDateTime
 
 
 
diff --git a/src/Bookhound/Parsers/Number.hs b/src/Bookhound/Parsers/Number.hs
--- a/src/Bookhound/Parsers/Number.hs
+++ b/src/Bookhound/Parsers/Number.hs
@@ -1,34 +1,34 @@
 module Bookhound.Parsers.Number (int, double, posInt, negInt, unsignedInt, hexInt, octInt, intLike) where
 
 import Bookhound.Parser            (ParseError (..), Parser, errorParser,
-                                    withError)
+                                    withErrorN)
 import Bookhound.ParserCombinators (IsMatch (..), (->>-), (<|>), (|+), (|?))
 import Bookhound.Parsers.Char      (dash, digit, dot, plus)
 
 
 hexInt :: Parser Integer
-hexInt = withError "Hex Int"
+hexInt = withErrorN (-1) "Hex Int"
  $ read <$> (is "0x" ->>-
              ((digit <|> oneOf ['A' .. 'F'] <|> oneOf ['a' .. 'f']) |+))
 
 octInt :: Parser Integer
-octInt = withError "Oct Int"
+octInt = withErrorN (-1) "Oct Int"
   $ read <$> (is "0o" ->>- (oneOf ['0' .. '7'] |+))
 
 unsignedInt :: Parser Integer
-unsignedInt = withError "Unsigned Int"
+unsignedInt = withErrorN (-1) "Unsigned Int"
   $ read <$> (digit |+)
 
 posInt :: Parser Integer
-posInt = withError "Positive Int"
+posInt = withErrorN (-1) "Positive Int"
   $ read <$> (plus |?) ->>- (digit |+)
 
 negInt :: Parser Integer
-negInt = withError "Negative Int"
+negInt = withErrorN (-1) "Negative Int"
   $ read <$> dash ->>- (digit |+)
 
 int :: Parser Integer
-int = withError "Int" $ negInt <|> posInt
+int = withErrorN (-1) "Int" $ negInt <|> posInt
 
 intLike :: Parser Integer
 intLike = parser <|> int
@@ -44,7 +44,7 @@
 
 
 double :: Parser Double
-double = withError "Double"
+double = withErrorN (-1) "Double"
   $ read <$> int ->>- (decimals |?) ->>- (expn |?) where
 
   decimals = dot ->>- unsignedInt
