diff --git a/composite-aeson.cabal b/composite-aeson.cabal
--- a/composite-aeson.cabal
+++ b/composite-aeson.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.32.0.
+-- This file has been generated from package.yaml by hpack version 0.33.0.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 919dc4a730a4bdf0886303870c36a4f70ad3fdb530eba59def3f5b105c4cb6b0
+-- hash: 7d5fd2a78928c12027d23895f74b3c815ebc88753dd2fb7f074caba91804d774
 
 name:           composite-aeson
-version:        0.7.1.0
+version:        0.7.2.0
 synopsis:       JSON for Vinyl records
 description:    Integration between Aeson and Vinyl records allowing records to be easily converted to JSON using automatic derivation, explicit formats, or a mix of both.
 category:       Records
@@ -39,26 +39,26 @@
   default-extensions: DataKinds FlexibleContexts FlexibleInstances GeneralizedNewtypeDeriving LambdaCase MultiParamTypeClasses MultiWayIf OverloadedStrings PatternSynonyms PolyKinds QuasiQuotes RankNTypes ScopedTypeVariables StandaloneDeriving StrictData TemplateHaskell TupleSections TypeApplications TypeFamilies TypeOperators ViewPatterns
   ghc-options: -Wall -O2
   build-depends:
-      aeson >=1.1.2.0 && <1.5
+      aeson >=1.1.2.0 && <1.6
     , aeson-better-errors >=0.9.1.0 && <0.10
     , base >=4.7 && <5
     , composite-base >=0.7 && <0.8
     , containers >=0.5.7.0 && <0.7
     , contravariant >=1.4 && <1.6
-    , generic-deriving >=1.11.2 && <1.13
-    , hashable >=1.2.6.1 && <1.3
-    , lens >=4.15.4 && <4.18
+    , generic-deriving >=1.11.2 && <1.14
+    , hashable >=1.2.6.1 && <1.4
+    , lens >=4.15.4 && <4.20
     , mmorph >=1.0.9 && <1.2
     , mtl >=2.2.1 && <2.3
-    , profunctors >=5.2.1 && <5.4
+    , profunctors >=5.2.1 && <5.6
     , scientific >=0.3.5.1 && <0.4
     , tagged >=0.8.5 && <0.9
-    , template-haskell >=2.11.1.0 && <2.15
+    , template-haskell >=2.11.1.0 && <2.17
     , text >=1.2.2.2 && <1.3
-    , time >=1.6.0.1 && <1.9
+    , time >=1.6.0.1 && <1.10
     , unordered-containers >=0.2.8.0 && <0.3
     , vector >=0.12.0.1 && <0.13
-    , vinyl >=0.5.3 && <0.13
+    , vinyl >=0.5.3 && <0.14
   default-language: Haskell2010
 
 test-suite composite-aeson-test
@@ -78,7 +78,7 @@
   ghc-options: -Wall -O2 -threaded -rtsopts -with-rtsopts=-N -fno-warn-orphans
   build-depends:
       QuickCheck
-    , aeson >=1.1.2.0 && <1.5
+    , aeson >=1.1.2.0 && <1.6
     , aeson-better-errors >=0.9.1.0 && <0.10
     , aeson-qq
     , base >=4.7 && <5
@@ -86,19 +86,19 @@
     , composite-base >=0.7 && <0.8
     , containers >=0.5.7.0 && <0.7
     , contravariant >=1.4 && <1.6
-    , generic-deriving >=1.11.2 && <1.13
-    , hashable >=1.2.6.1 && <1.3
+    , generic-deriving >=1.11.2 && <1.14
+    , hashable >=1.2.6.1 && <1.4
     , hspec
-    , lens >=4.15.4 && <4.18
+    , lens >=4.15.4 && <4.20
     , mmorph >=1.0.9 && <1.2
     , mtl >=2.2.1 && <2.3
-    , profunctors >=5.2.1 && <5.4
+    , profunctors >=5.2.1 && <5.6
     , scientific >=0.3.5.1 && <0.4
     , tagged >=0.8.5 && <0.9
-    , template-haskell >=2.11.1.0 && <2.15
+    , template-haskell >=2.11.1.0 && <2.17
     , text >=1.2.2.2 && <1.3
-    , time >=1.6.0.1 && <1.9
+    , time >=1.6.0.1 && <1.10
     , unordered-containers >=0.2.8.0 && <0.3
     , vector >=0.12.0.1 && <0.13
-    , vinyl >=0.5.3 && <0.13
+    , vinyl >=0.5.3 && <0.14
   default-language: Haskell2010
diff --git a/src/Composite/Aeson/Formats/DateTime.hs b/src/Composite/Aeson/Formats/DateTime.hs
--- a/src/Composite/Aeson/Formats/DateTime.hs
+++ b/src/Composite/Aeson/Formats/DateTime.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 module Composite.Aeson.Formats.DateTime
   ( DateTimeFormat(..), regularDateTimeFormat
   , dateTimeJsonFormat
@@ -94,13 +95,19 @@
 
 instance Monad SuccessOrFail where
   return = Success
-  fail   = Fail
-
   Success a >>= k = k a
   Fail    f >>= _ = Fail f
+#if MIN_VERSION_base(4,13,0)
+instance MonadFail SuccessOrFail where
+#endif
+  fail   = Fail
 
 -- |Evaluate some action of type @Monad m => m a@ and apply either the first or second function based on whether the computation completed or used @fail@.
+#if MIN_VERSION_base(4,13,0)
+successOrFail :: (String -> b) -> (a -> b) -> (forall m. MonadFail m => m a) -> b
+#else
 successOrFail :: (String -> b) -> (a -> b) -> (forall m. Monad m => m a) -> b
+#endif
 successOrFail _ f (Success a) = f a
 successOrFail f _ (Fail    s) = f s
 
diff --git a/src/Composite/Aeson/Formats/Generic.hs b/src/Composite/Aeson/Formats/Generic.hs
--- a/src/Composite/Aeson/Formats/Generic.hs
+++ b/src/Composite/Aeson/Formats/Generic.hs
@@ -182,11 +182,11 @@
     [f] ->
       case lookup f (NEL.toList iAs) of
         Just (FromJson iA) -> ABE.key f iA
-        Nothing -> fail $ "unknown field " <> unpack f <> ", expected one of " <> expected
+        Nothing -> throwError $ ABE.InvalidJSON $ "unknown field " <> unpack f <> ", expected one of " <> expected
     [] ->
-      fail $ "expected an object with one field (" <> expected <> ") not an empty object"
+      throwError $ ABE.InvalidJSON $ "expected an object with one field (" <> expected <> ") not an empty object"
     _ ->
-      fail $ "expected an object with one field (" <> expected <> ") not many fields"
+      throwError $ ABE.InvalidJSON $ "expected an object with one field (" <> expected <> ") not many fields"
   where
     expected = expectedFieldsForInputs iAs
 
diff --git a/src/Composite/Aeson/Formats/InternalTH.hs b/src/Composite/Aeson/Formats/InternalTH.hs
--- a/src/Composite/Aeson/Formats/InternalTH.hs
+++ b/src/Composite/Aeson/Formats/InternalTH.hs
@@ -3,6 +3,7 @@
   ) where
 
 import Composite.Aeson.Base (JsonFormat(JsonFormat), JsonProfunctor(JsonProfunctor))
+import Control.Monad.Except (throwError)
 import qualified Data.Aeson as Aeson
 import qualified Data.Aeson.BetterErrors as ABE
 import qualified Data.HashMap.Lazy as HM
@@ -79,7 +80,7 @@
                      ABE.withArray Right >>= \ a ->
                        if V.length a == $(lift arity)
                          then pure ()
-                         else fail $(lift $ "expected an array of exactly " <> show arity <> " elements")
+                         else throwError $ ABE.InvalidJSON $  $(lift $ "expected an array of exactly " <> show arity <> " elements")
                      |]
                  ]
               ++ map ( \ (n, valName, iName) ->
diff --git a/src/Composite/Aeson/Formats/Provided.hs b/src/Composite/Aeson/Formats/Provided.hs
--- a/src/Composite/Aeson/Formats/Provided.hs
+++ b/src/Composite/Aeson/Formats/Provided.hs
@@ -5,6 +5,7 @@
 import Composite.Aeson.Formats.Generic (SumStyle, abeJsonFormat, aesonJsonFormat, jsonArrayFormat, jsonObjectFormat, jsonSumFormat)
 import Composite.Aeson.Formats.InternalTH (makeTupleFormats, makeNamedTupleFormats)
 import Control.Arrow (first)
+import Control.Monad.Except (throwError)
 import Control.Lens (_2, _Wrapped, over, view)
 import qualified Data.Aeson as Aeson
 import qualified Data.Aeson.BetterErrors as ABE
@@ -116,7 +117,7 @@
 -- |'JsonFormat' for 'NonEmpty' which maps to a JSON array.
 nonEmptyListJsonFormat :: JsonFormat e a -> JsonFormat e (NonEmpty a)
 nonEmptyListJsonFormat =
-  jsonArrayFormat NEL.toList (maybe (fail "expected nonempty array") pure . NEL.nonEmpty)
+  jsonArrayFormat NEL.toList (maybe (throwError $ ABE.InvalidJSON $ fail "expected nonempty array") pure . NEL.nonEmpty)
 
 -- |JSON format for '()' which maps to JSON as @null@.
 nullJsonFormat :: JsonFormat e ()
