diff --git a/Criterion/Report.hs b/Criterion/Report.hs
--- a/Criterion/Report.hs
+++ b/Criterion/Report.hs
@@ -123,10 +123,11 @@
     -- includes, only top level
     templates <- getTemplateDir
     template <- includeTemplate (includeFile [templates]) template0
+    reports' <- mapM inner reports
 
     let context = object
             [ "json"                .= reports
-            , "report"              .= map inner reports
+            , "report"              .= reports'
             , "js-jquery"           .= jQuery
             , "js-flot"             .= flot
             , "js-flot-errorbars"   .= flotErrorbars
@@ -148,11 +149,7 @@
       -- mustache conventions, but redesigning the template to avoid this
       -- warning would be more work than just substituting the array directly.
       unless (warning == MustacheDirectlyRenderedValue (Key ["json"])) $
-        mapM_ (hPutStrLn stderr)
-         [ "criterion: warning:"
-         , "  " ++ displayMustacheWarning warning
-         , ""
-         ]
+        criterionWarning $ displayMustacheWarning warning
     return formatted
   where
     jQueryFileContents, flotFileContents :: IO T.Text
@@ -196,8 +193,11 @@
             _         -> y
         _         -> y
 
-    inner r@Report {..} = merge reportAnalysis $ merge reportOutliers $ object
-        [ "name"                  .= reportName
+    inner :: Report -> IO Value
+    inner r@Report {..} = do
+      reportName' <- sanitizeJSString $ T.pack reportName
+      return $ merge reportAnalysis $ merge reportOutliers $ object
+        [ "name"                  .= reportName'
         , "json"                  .= TLE.decodeUtf8 (encode r)
         , "number"                .= reportNumber
         , "iters"                 .= vector "x" iters
@@ -225,6 +225,24 @@
                = confidenceInterval anMean
         (anStdDevLowerBound, anStdDevUpperBound)
                = confidenceInterval anStdDev
+
+        sanitizeJSString :: T.Text -> IO T.Text
+        sanitizeJSString str = do
+          let pieces = T.splitOn "\n" str
+          case pieces of
+            (_word1:_word2:_) -> do
+              criterionWarning $
+                "Report name " ++ show str ++ " contains newlines, which " ++
+                "will be replaced with spaces in the HTML report."
+              return $ T.unwords pieces
+            _ -> return str
+
+criterionWarning :: String -> IO ()
+criterionWarning msg =
+  hPutStrLn stderr $ unlines
+    [ "criterion: warning:"
+    , "  " ++ msg
+    ]
 
 -- | Render the elements of a vector.
 --
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,8 @@
+1.5.7.0
+
+* Warn if an HTML report name contains newlines, and replace newlines with
+  whitespace to avoid syntax errors in the report itself.
+
 1.5.6.2
 
 * Use unescaped HTML in the `json.tpl` template.
diff --git a/criterion.cabal b/criterion.cabal
--- a/criterion.cabal
+++ b/criterion.cabal
@@ -1,5 +1,5 @@
 name:           criterion
-version:        1.5.6.2
+version:        1.5.7.0
 synopsis:       Robust, reliable performance measurement and analysis
 license:        BSD3
 license-file:   LICENSE
@@ -27,7 +27,8 @@
   GHC==8.2.2,
   GHC==8.4.4,
   GHC==8.6.5,
-  GHC==8.8.1
+  GHC==8.8.3,
+  GHC==8.10.1
 
 data-files:
   templates/*.css
diff --git a/examples/Maps.hs b/examples/Maps.hs
--- a/examples/Maps.hs
+++ b/examples/Maps.hs
@@ -24,15 +24,16 @@
 
 numbers :: IO (V, V, V)
 numbers = do
-  random <- withSystemRandom . asGenIO $ \gen -> uniformVector gen 40000
+  gen <- createSystemRandom
+  random <- uniformVector gen 40000
   let sorted    = G.modify I.sort random
       revsorted = G.reverse sorted
   return (random, sorted, revsorted)
 
 strings :: IO (B, B, B)
 strings = do
-  random <- withSystemRandom . asGenIO $ \gen ->
-    V.replicateM 10000 $
+  gen <- createSystemRandom
+  random <- V.replicateM 10000 $
       (pack . U.toList) `fmap` (uniformVector gen =<< uniformR (1,16) gen)
   let sorted    = G.modify I.sort random
       revsorted = G.reverse sorted
diff --git a/examples/criterion-examples.cabal b/examples/criterion-examples.cabal
--- a/examples/criterion-examples.cabal
+++ b/examples/criterion-examples.cabal
@@ -9,7 +9,7 @@
 maintainer:    Bryan O'Sullivan <bos@serpentine.com>
 category:      Benchmarks
 build-type:    Simple
-cabal-version: >=1.8
+cabal-version: >=1.10
 tested-with:
   GHC==7.4.2,
   GHC==7.6.3,
@@ -19,7 +19,8 @@
   GHC==8.2.2,
   GHC==8.4.4,
   GHC==8.6.5,
-  GHC==8.8.1
+  GHC==8.8.3,
+  GHC==8.10.1
 
 flag conduit-vs-pipes
   default: True
@@ -30,6 +31,7 @@
 executable fibber
   main-is: Fibber.hs
 
+  default-language: Haskell2010
   ghc-options: -Wall -rtsopts
   build-depends:
     base == 4.*,
@@ -41,6 +43,7 @@
 
   main-is: ConduitVsPipes.hs
 
+  default-language: Haskell2010
   ghc-options: -Wall -rtsopts
   build-depends:
     base >= 4.8 && < 5,
@@ -55,6 +58,7 @@
 
   main-is: Maps.hs
 
+  default-language: Haskell2010
   ghc-options: -Wall -rtsopts
   build-depends:
     base == 4.*,
@@ -63,7 +67,7 @@
     criterion,
     deepseq,
     hashable,
-    mwc-random,
+    mwc-random >= 0.13.1,
     unordered-containers,
     vector,
     vector-algorithms
@@ -71,6 +75,7 @@
 executable overhead
   main-is: Overhead.hs
 
+  default-language: Haskell2010
   ghc-options: -Wall -rtsopts
   build-depends:
     base == 4.*,
@@ -80,6 +85,7 @@
 executable bad-read-file
   main-is: BadReadFile.hs
 
+  default-language: Haskell2010
   ghc-options: -Wall -rtsopts
   build-depends:
     base == 4.*,
@@ -88,6 +94,7 @@
 executable good-read-file
   main-is: GoodReadFile.hs
 
+  default-language: Haskell2010
   ghc-options: -Wall -rtsopts
   build-depends:
     base == 4.*,
@@ -96,6 +103,7 @@
 executable extensible-cli
   main-is: ExtensibleCLI.hs
 
+  default-language: Haskell2010
   ghc-options: -Wall -rtsopts
   build-depends:
     base == 4.*,
@@ -109,6 +117,7 @@
 --   main-is: Judy.hs
 --
 --   buildable: False
+--   default-language: Haskell2010
 --   ghc-options: -Wall -rtsopts
 --   build-depends:
 --     base == 4.*,
