diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+## 1.1.5
+
+Added `sinkParserEither` ([pull request #189](https://github.com/snoyberg/conduit/pull/189))
diff --git a/Data/Conduit/Attoparsec.hs b/Data/Conduit/Attoparsec.hs
--- a/Data/Conduit/Attoparsec.hs
+++ b/Data/Conduit/Attoparsec.hs
@@ -13,6 +13,7 @@
 module Data.Conduit.Attoparsec
     ( -- * Sink
       sinkParser
+    , sinkParserEither
       -- * Conduit
     , conduitParser
     , conduitParserEither
@@ -115,6 +116,12 @@
 sinkParser :: (AttoparsecInput a, MonadThrow m) => A.Parser a b -> Consumer a m b
 sinkParser = fmap snd . sinkParserPosErr (Position 1 1)
 
+-- | Same as 'sinkParser', but we return an 'Either' type instead
+-- of raising an exception.
+--
+-- Since 1.1.5
+sinkParserEither :: (AttoparsecInput a, Monad m) => A.Parser a b -> Consumer a m (Either ParseError b)
+sinkParserEither = (fmap.fmap) snd . sinkParserPos (Position 1 1)
 
 
 -- | Consume a stream of parsed tokens, returning both the token and
diff --git a/conduit-extra.cabal b/conduit-extra.cabal
--- a/conduit-extra.cabal
+++ b/conduit-extra.cabal
@@ -1,5 +1,5 @@
 Name:                conduit-extra
-Version:             1.1.4.2
+Version:             1.1.5
 Synopsis:            Batteries included conduit: adapters for common libraries.
 Description:
     The conduit package itself maintains relative small dependencies. The purpose of this package is to collect commonly used utility functions wrapping other library dependencies, without depending on heavier-weight dependencies. The basic idea is that this package should only depend on haskell-platform packages and conduit.
@@ -15,6 +15,7 @@
     test/random
     test/filesystem/*.txt
     test/filesystem/bin/*.txt
+    ChangeLog.md
 
 Library
   Exposed-modules:     Data.Conduit.Attoparsec
diff --git a/test/Data/Conduit/AttoparsecSpec.hs b/test/Data/Conduit/AttoparsecSpec.hs
--- a/test/Data/Conduit/AttoparsecSpec.hs
+++ b/test/Data/Conduit/AttoparsecSpec.hs
@@ -24,84 +24,119 @@
                 badCol = 6
                 parser = Data.Attoparsec.Text.endOfInput <|> (Data.Attoparsec.Text.notChar 'b' >> parser)
                 sink = sinkParser parser
+                sink' = sinkParserEither parser
             ea <- runExceptionT $ CL.sourceList input $$ sink
             case ea of
                 Left e ->
                     case fromException e of
                         Just pe -> do
                             errorPosition pe `shouldBe` Position badLine badCol
+            ea' <- CL.sourceList input $$ sink'
+            case ea' of
+                Left pe ->
+                    errorPosition pe `shouldBe` Position badLine badCol
         it "works for bytestring" $ do
             let input = ["aaa\na", "aaa\n\n", "aaa", "aab\n\naaaa"]
                 badLine = 4
                 badCol = 6
                 parser = Data.Attoparsec.ByteString.Char8.endOfInput <|> (Data.Attoparsec.ByteString.Char8.notChar 'b' >> parser)
                 sink = sinkParser parser
+                sink' = sinkParserEither parser
             ea <- runExceptionT $ CL.sourceList input $$ sink
             case ea of
                 Left e ->
                     case fromException e of
                         Just pe -> do
                             errorPosition pe `shouldBe` Position badLine badCol
+            ea' <- CL.sourceList input $$ sink'
+            case ea' of
+                Left pe ->
+                    errorPosition pe `shouldBe` Position badLine badCol
         it "works in last chunk" $ do
             let input = ["aaa\na", "aaa\n\n", "aaa", "aab\n\naaaa"]
                 badLine = 6
                 badCol = 5
                 parser = Data.Attoparsec.Text.char 'c' <|> (Data.Attoparsec.Text.anyChar >> parser)
                 sink = sinkParser parser
+                sink' = sinkParserEither parser
             ea <- runExceptionT $ CL.sourceList input $$ sink
             case ea of
                 Left e ->
                     case fromException e of
                         Just pe -> do
                             errorPosition pe `shouldBe` Position badLine badCol
+            ea' <- CL.sourceList input $$ sink'
+            case ea' of
+                Left pe ->
+                    errorPosition pe `shouldBe` Position badLine badCol
         it "works in last chunk" $ do
             let input = ["aaa\na", "aaa\n\n", "aaa", "aa\n\naaaab"]
                 badLine = 6
                 badCol = 6
                 parser = Data.Attoparsec.Text.string "bc" <|> (Data.Attoparsec.Text.anyChar >> parser)
                 sink = sinkParser parser
+                sink' = sinkParserEither parser
             ea <- runExceptionT $ CL.sourceList input $$ sink
             case ea of
                 Left e ->
                     case fromException e of
                         Just pe -> do
                             errorPosition pe `shouldBe` Position badLine badCol
+            ea' <- CL.sourceList input $$ sink'
+            case ea' of
+                Left pe ->
+                    errorPosition pe `shouldBe` Position badLine badCol
         it "works after new line in text" $ do
             let input = ["aaa\n", "aaa\n\n", "aaa", "aa\nb\naaaa"]
                 badLine = 5
                 badCol = 1
                 parser = Data.Attoparsec.Text.endOfInput <|> (Data.Attoparsec.Text.notChar 'b' >> parser)
                 sink = sinkParser parser
+                sink' = sinkParserEither parser
             ea <- runExceptionT $ CL.sourceList input $$ sink
             case ea of
                 Left e ->
                     case fromException e of
                         Just pe -> do
                             errorPosition pe `shouldBe` Position badLine badCol
+            ea' <- CL.sourceList input $$ sink'
+            case ea' of
+                Left pe ->
+                    errorPosition pe `shouldBe` Position badLine badCol
         it "works after new line in bytestring" $ do
             let input = ["aaa\n", "aaa\n\n", "aaa", "aa\nb\naaaa"]
                 badLine = 5
                 badCol = 1
                 parser = Data.Attoparsec.ByteString.Char8.endOfInput <|> (Data.Attoparsec.ByteString.Char8.notChar 'b' >> parser)
                 sink = sinkParser parser
+                sink' = sinkParserEither parser
             ea <- runExceptionT $ CL.sourceList input $$ sink
             case ea of
                 Left e ->
                     case fromException e of
                         Just pe -> do
                             errorPosition pe `shouldBe` Position badLine badCol
+            ea' <- CL.sourceList input $$ sink'
+            case ea' of
+                Left pe ->
+                    errorPosition pe `shouldBe` Position badLine badCol
         it "works for first line" $ do
             let input = ["aab\na", "aaa\n\n", "aaa", "aab\n\naaaa"]
                 badLine = 1
                 badCol = 3
                 parser = Data.Attoparsec.Text.endOfInput <|> (Data.Attoparsec.Text.notChar 'b' >> parser)
                 sink = sinkParser parser
+                sink' = sinkParserEither parser
             ea <- runExceptionT $ CL.sourceList input $$ sink
             case ea of
                 Left e ->
                     case fromException e of
                         Just pe -> do
                             errorPosition pe `shouldBe` Position badLine badCol
+            ea' <- CL.sourceList input $$ sink'
+            case ea' of
+                Left pe ->
+                    errorPosition pe `shouldBe` Position badLine badCol
 
     describe "conduitParser" $ do
         it "parses a repeated stream" $ do
