diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,10 @@
+## Version 0.5.3.2
+
+ * Proper exception on hanging doublequote ([PR #222](https://github.com/haskell-hvr/cassava/pull/222)).
+ * Allow latest `hashable`.
+ * Build tested with GHC 8.0 - 9.10.1.
+ * Functionality tested with GHC 8.4 - 9.10.1.
+
 ## Version 0.5.3.1
 
  * Remove support for GHC 7.
diff --git a/cassava.cabal b/cassava.cabal
--- a/cassava.cabal
+++ b/cassava.cabal
@@ -1,6 +1,6 @@
 cabal-version:       1.12
 Name:                cassava
-Version:             0.5.3.1
+Version:             0.5.3.2
 Synopsis:            A CSV parsing and encoding library
 Description: {
 
@@ -43,9 +43,9 @@
                      CHANGES.md,
                      README.md
 Tested-with:
-  GHC == 9.10.0
+  GHC == 9.10.1
   GHC == 9.8.2
-  GHC == 9.6.5
+  GHC == 9.6.6
   GHC == 9.4.8
   GHC == 9.2.8
   GHC == 9.0.2
@@ -68,7 +68,6 @@
     BangPatterns
     CPP
     DataKinds
-    DataKinds
     DefaultSignatures
     DeriveFunctor
     FlexibleContexts
@@ -77,7 +76,6 @@
     MultiParamTypeClasses
     OverloadedStrings
     PolyKinds
-    PolyKinds
     Rank2Types
     ScopedTypeVariables
     TypeOperators
@@ -106,7 +104,7 @@
     , bytestring   >= 0.10.4   && < 0.13
     , containers   >= 0.4.2    && < 0.8
     , deepseq      >= 1.1      && < 1.6
-    , hashable                    < 1.5
+    , hashable                    < 2
     , scientific   >= 0.3.4.7  && < 0.4
     , text                        < 2.2
     , text-short   == 0.1.*
@@ -138,7 +136,7 @@
   Main-is: UnitTests.hs
   -- dependencies with version constraints inherited via lib:cassava
   Build-depends: attoparsec
-               , base
+               , base                   >= 4.11 && < 5
                , bytestring
                , cassava
                , hashable
@@ -160,12 +158,10 @@
     -Wall
     -- https://ghc.haskell.org/trac/ghc/wiki/Migration/8.0#Recommendationsforforward-compatibility
     -Wcompat
+    -Wcpp-undef
     -Wnoncanonical-monad-instances
 
   if impl(ghc >= 8.8)
     ghc-options: -Wno-star-is-type
   else
     ghc-options: -Wnoncanonical-monadfail-instances
-
-  if impl(ghc >= 8.2)
-    ghc-options: -Wcpp-undef
diff --git a/src/Data/Csv/Parser.hs b/src/Data/Csv/Parser.hs
--- a/src/Data/Csv/Parser.hs
+++ b/src/Data/Csv/Parser.hs
@@ -149,17 +149,20 @@
 escapedField :: AL.Parser S.ByteString
 escapedField = do
     _ <- dquote
-    -- The scan state is 'True' if the previous character was a double
-    -- quote.  We need to drop a trailing double quote left by scan.
-    s <- S.init <$> (A.scan False $ \s c -> if c == doubleQuote
-                                            then Just (not s)
-                                            else if s then Nothing
-                                                 else Just False)
-    if doubleQuote `S.elem` s
-        then case Z.parse unescape s of
-            Right r  -> return r
-            Left err -> fail err
-        else return s
+    -- The scan state is 'True' if the previous character was a double quote.
+    s' <- A.scan False $ \s c -> if c == doubleQuote
+                                 then Just (not s)
+                                 else if s then Nothing
+                                      else Just False
+    -- We need to drop a trailing double quote left by scan.
+    if S.null s'
+      then fail "trailing double quote"
+      else let s = S.init s'
+           in if doubleQuote `S.elem` s
+              then case Z.parse unescape s of
+                     Right r  -> return r
+                     Left err -> fail err
+              else return s
 
 unescapedField :: Word8 -> AL.Parser S.ByteString
 unescapedField !delim = A.takeWhile (\ c -> c /= doubleQuote &&
diff --git a/tests/UnitTests.hs b/tests/UnitTests.hs
--- a/tests/UnitTests.hs
+++ b/tests/UnitTests.hs
@@ -17,6 +17,7 @@
 import qualified Data.Text.Lazy as LT
 import qualified Data.Vector as V
 import qualified Data.Foldable as F
+import Data.List (isPrefixOf)
 import Data.Word
 import Numeric.Natural
 import GHC.Generics (Generic)
@@ -48,6 +49,14 @@
                 "      input: " ++ show (BL8.unpack input) ++ "\n" ++
                 "parse error: " ++ err
 
+decodeFailsWith :: BL.ByteString -> String -> Assertion
+decodeFailsWith input expected = case decode NoHeader input of
+    Right r  -> assertFailure $ "input: " ++ show (BL8.unpack input) ++ "\n" ++
+                "retuned: " ++ show (r :: (V.Vector (V.Vector B.ByteString))) ++ "\n" ++
+                "whereas should have failed with " <> expected
+    Left err -> assertBool ("got " <> err <> "\ninstead of " <> expected)
+                $ ("parse error ("++expected++")") `isPrefixOf` err
+
 encodesAs :: [[B.ByteString]] -> BL.ByteString -> Assertion
 encodesAs input expected =
     encode (map V.fromList input) @?= expected
@@ -158,6 +167,11 @@
       [ testGroup "decode" $ map streamingDecodeTest decodeTests
       , testGroup "decodeWith" $ map streamingDecodeWithTest decodeWithTests
       ]
+    , testGroup "failing"
+      [ testCase "escapedMalformed0" $
+          "baz,\"" `decodeFailsWith` "Failed reading: trailing double quote"
+      ]
+
     ]
   where
     rfc4180Input = BL8.pack $
@@ -178,6 +192,10 @@
            [["a", "b", "c"], ["d", "e", "f"]])
         , ("leadingSpace", " a,  b,   c\n",  [[" a", "  b", "   c"]])
         , ("rfc4180", rfc4180Input, rfc4180Output)
+        , ("escapedDoubleQuotes"
+          , "\"x,y\",z\nbaz,\"bar\nfoo,\""
+          , [["x,y", "z"], ["baz", "bar\nfoo,"]]
+          )
         ]
     decodeWithTests =
         [ ("tab-delim", defDec { decDelimiter = 9 }, "1\t2", [["1", "2"]])
