diff --git a/LICENCE b/LICENCE
--- a/LICENCE
+++ b/LICENCE
@@ -1,4 +1,4 @@
-Copyright (c) 2017-2018, Commonwealth Scientific and Industrial Research Organisation
+Copyright (c) 2017-2019, Commonwealth Scientific and Industrial Research Organisation
 (CSIRO) ABN 41 687 119 230.
 
 All rights reserved.
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,9 @@
 # Revision history for sv
 
+## 1.3.1 -- 2019-04-02
+
+* Update to sv-core 0.4.1
+
 ## 1.3.0.1 -- 2019-02-26
 
 * Fix an occasionally failing property-test
diff --git a/src/Data/Sv.hs b/src/Data/Sv.hs
--- a/src/Data/Sv.hs
+++ b/src/Data/Sv.hs
@@ -3,7 +3,7 @@
 
 {-|
 Module      : Data.Sv
-Copyright   : (C) CSIRO 2017-2018
+Copyright   : (C) CSIRO 2017-2019
 License     : BSD3
 Maintainer  : George Wilson <george.wilson@data61.csiro.au>
 Stability   : experimental
@@ -148,7 +148,7 @@
             in  case _headedness opts of
               Unheaded ->
                 badConfig $ mconcat
-                  [ "Your ParseOptions indicates a CSV with no header (Unheaded),\n"
+                  [ "Your ParseOptions indicates a CSV with no header (Unheaded), "
                   , "but your decoder requires column names."
                   ]
               Headed   ->
diff --git a/src/Data/Sv/Decode.hs b/src/Data/Sv/Decode.hs
--- a/src/Data/Sv/Decode.hs
+++ b/src/Data/Sv/Decode.hs
@@ -1,6 +1,6 @@
 {-|
 Module      : Data.Sv.Decode
-Copyright   : (C) CSIRO 2017-2018
+Copyright   : (C) CSIRO 2017-2019
 License     : BSD3
 Maintainer  : George Wilson <george.wilson@data61.csiro.au>
 Stability   : experimental
diff --git a/src/Data/Sv/Encode.hs b/src/Data/Sv/Encode.hs
--- a/src/Data/Sv/Encode.hs
+++ b/src/Data/Sv/Encode.hs
@@ -1,6 +1,6 @@
 {-|
 Module      : Data.Sv.Encode
-Copyright   : (C) CSIRO 2017-2018
+Copyright   : (C) CSIRO 2017-2019
 License     : BSD3
 Maintainer  : George Wilson <george.wilson@data61.csiro.au>
 Stability   : experimental
diff --git a/src/Data/Sv/Parse.hs b/src/Data/Sv/Parse.hs
--- a/src/Data/Sv/Parse.hs
+++ b/src/Data/Sv/Parse.hs
@@ -1,6 +1,6 @@
 {-|
 Module      : Data.Sv.Parse
-Copyright   : (C) CSIRO 2017-2018
+Copyright   : (C) CSIRO 2017-2019
 License     : BSD3
 Maintainer  : George Wilson <george.wilson@data61.csiro.au>
 Stability   : experimental
diff --git a/src/Data/Sv/Structure.hs b/src/Data/Sv/Structure.hs
--- a/src/Data/Sv/Structure.hs
+++ b/src/Data/Sv/Structure.hs
@@ -1,6 +1,6 @@
 {-|
 Module      : Data.Sv.Structure
-Copyright   : (C) CSIRO 2017-2018
+Copyright   : (C) CSIRO 2017-2019
 License     : BSD3
 Maintainer  : George Wilson <george.wilson@data61.csiro.au>
 Stability   : experimental
diff --git a/sv.cabal b/sv.cabal
--- a/sv.cabal
+++ b/sv.cabal
@@ -1,10 +1,10 @@
 name:                sv
-version:             1.3.0.1
+version:             1.3.1
 license:             BSD3
 license-file:        LICENCE
 author:              George Wilson
 maintainer:          george@qfpl.io
-copyright:           Copyright (c) 2017-2018, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230.
+copyright:           Copyright (c) 2017-2019, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230.
 category:            CSV, Text, Web
 synopsis:
   Encode and decode separated values (CSV, PSV, ...)
@@ -77,7 +77,7 @@
                      , GHC == 8.0.2
                      , GHC == 8.2.2
                      , GHC == 8.4.4
-                     , GHC == 8.6.3
+                     , GHC == 8.6.4
 
 source-repository    head
   type:              git
@@ -98,7 +98,7 @@
                        , contravariant >= 1.2 && < 1.6
                        , hw-dsv >= 0.2.1 && < 0.4
                        , semigroupoids >= 5 && < 5.4
-                       , sv-core >= 0.4 && < 0.5
+                       , sv-core == 0.4.1.*
                        , transformers >= 0.2 && < 0.6
                        , utf8-string >= 1 && < 1.1
                        , validation >= 1 && < 1.1
diff --git a/test/Data/Sv/DecodeTest.hs b/test/Data/Sv/DecodeTest.hs
--- a/test/Data/Sv/DecodeTest.hs
+++ b/test/Data/Sv/DecodeTest.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE DeriveFoldable #-}
 {-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE DeriveTraversable #-}
+{-# LANGUAGE OverloadedLists #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Data.Sv.DecodeTest (test_Decode) where
@@ -12,7 +13,7 @@
 import Data.Functor.Alt ((<!>))
 import Data.List.NonEmpty (NonEmpty ((:|)))
 import Text.Read (readMaybe)
-import Data.Semigroup (Semigroup)
+import Data.Semigroup (Semigroup ((<>)))
 import Data.Semigroupoid (Semigroupoid (o))
 import qualified Data.Vector as V
 import Test.Tasty (TestTree, testGroup)
@@ -29,6 +30,7 @@
   , varyingLengthTest
   , semigroupoidTest
   , namedTest
+  , displayErrorsTest
   ]
 
 data IntOrString =
@@ -197,8 +199,48 @@
         Failure (DecodeErrors (MissingHeader:|[]))
   , testCase "misconfigured" $
       parseDecodeNamed inOrder opts namedCsv @?=
-        Failure (DecodeErrors (
-          BadConfig "Your ParseOptions indicates a CSV with no header (Unheaded),\nbut your decoder requires column names."
-          :|[]
-        ))
+        Failure badConfigErrors
+  ]
+
+badConfigErrors :: DecodeErrors ByteString
+badConfigErrors =
+  DecodeErrors (
+    BadConfig "Your ParseOptions indicates a CSV with no header (Unheaded), but your decoder requires column names."
+      :|[]
+  )
+
+displayErrorsTest :: TestTree
+displayErrorsTest = testGroup "displayErrors" [
+    testCase "single error / BadParse" $
+      displayErrors (DecodeErrors (BadParse "missing comma":|[])) @?=
+        "The following error occurred:\n" <>
+        "  Parsing the document failed. The error was: missing comma"
+  , testCase "two errors / UnexpectedEndOfRow, BadDecode" $
+      displayErrors (DecodeErrors (UnexpectedEndOfRow:|[BadDecode "Could not decode \"3.z\" as a Double"])) @?=
+        "The following 2 errors occurred:\n" <>
+        "  Expected more fields, but the row ended.\n" <>
+        "  Decoding a field failed: Could not decode \"3.z\" as a Double"
+  , testCase "BadConfig" $
+      displayErrors badConfigErrors @?=
+        "The following error occurred:\n" <>
+        "  sv was misconfigured: Your ParseOptions indicates a CSV with no header (Unheaded), but your decoder requires column names."
+  , testCase "Missing Columns" $
+      displayErrors (DecodeErrors (MissingColumn "name":|[MissingColumn "age", MissingColumn "address"])) @?=
+        "The following 3 errors occurred:\n" <>
+        "  Could not find required column \"name\"\n" <>
+        "  Could not find required column \"age\"\n" <>
+        "  Could not find required column \"address\""
+  , testCase "MissingHeader" $
+      displayErrors (DecodeErrors (MissingHeader:|[])) @?=
+        "The following error occurred:\n" <>
+        "  A header row was required, but one was not found."
+  , testCase "ExpectedEndOfRow" $
+      displayErrors (DecodeErrors (ExpectedEndOfRow ["hello", "yes", "no"]:|[])) @?=
+        "The following error occurred:\n" <>
+        "  Expected fewer fields in the row. The extra fields contained: \"hello\", \"yes\", \"no\""
+  , testCase "UnknownCategoricalValue" $
+      displayErrors (DecodeErrors (UnknownCategoricalValue "yes" [["y","true","ok"],["n","false","nope"]] :|[])) @?=
+        "The following error occurred:\n" <>
+        "  Unknown categorical value found: \"yes\". " <>
+          "Expected one of: \"y\", \"true\", \"ok\", \"n\", \"false\", \"nope\""
   ]
