diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,10 @@
 Changelog for HLint (* = breaking change)
 
+2.1.2, released 2018-04-16
+    #407, don't error on unknown extensions on the command line
+    Require extra-1.6.6
+    #464, add more hints for concatMap
+    #462, ignore home directory when it isn't present
 2.1.1, released 2018-03-24
     #457, suggest turning on LambdaCase if necessary
     #457, add RequiresExtension note
diff --git a/data/hlint.yaml b/data/hlint.yaml
--- a/data/hlint.yaml
+++ b/data/hlint.yaml
@@ -122,6 +122,8 @@
     - warn: {lhs: isPrefixOf (reverse x) (reverse y), rhs: isSuffixOf x y}
     - warn: {lhs: "foldr (++) []", rhs: concat}
     - warn: {lhs: foldr (++) "", rhs: concat}
+    - warn: {lhs: "foldr ((++) . f) []", rhs: concatMap f}
+    - warn: {lhs: foldr ((++) . f) "", rhs: concatMap f}
     - warn: {lhs: "foldl (++) []", rhs: concat, note: IncreasesLaziness}
     - warn: {lhs: foldl (++) "", rhs: concat, note: IncreasesLaziness}
     - warn: {lhs: foldl f (head x) (tail x), rhs: foldl1 f x}
diff --git a/hlint.cabal b/hlint.cabal
--- a/hlint.cabal
+++ b/hlint.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.18
 build-type:         Simple
 name:               hlint
-version:            2.1.1
+version:            2.1.2
 license:            BSD3
 license-file:       LICENSE
 category:           Development
@@ -57,7 +57,7 @@
         haskell-src-exts-util >= 0.2.1.2,
         uniplate >= 1.5,
         ansi-terminal >= 0.6.2,
-        extra >= 1.4.9,
+        extra >= 1.6.6,
         refact >= 0.3,
         aeson >= 1.1.2.0
 
diff --git a/src/CmdLine.hs b/src/CmdLine.hs
--- a/src/CmdLine.hs
+++ b/src/CmdLine.hs
@@ -10,25 +10,28 @@
 import Control.Monad.Extra
 import Data.Char
 import Data.List
+import Data.Maybe
+import Data.Functor
+import HSE.All(CppFlags(..))
+import Language.Haskell.Exts(defaultParseMode, baseLanguage)
+import Language.Haskell.Exts.Extension
+import Language.Preprocessor.Cpphs
 import System.Console.ANSI(hSupportsANSI)
-import System.Console.CmdArgs.Implicit
 import System.Console.CmdArgs.Explicit(helpText, HelpFormat(..))
+import System.Console.CmdArgs.Implicit
 import System.Directory.Extra
+import System.Environment.Extra
 import System.Exit
 import System.FilePath
 import System.IO
-import System.Process(readProcess)
-import Language.Preprocessor.Cpphs
-import HSE.All(CppFlags(..))
-import Language.Haskell.Exts(defaultParseMode, baseLanguage)
-import Language.Haskell.Exts.Extension
-import Data.Maybe
-import System.Environment.Extra
+import System.IO.Error
 import System.Info.Extra
+import System.Process
 
 import Util
 import Paths_hlint
 import Data.Version
+import Prelude
 
 
 getCmd :: [String] -> IO Cmd
@@ -217,11 +220,12 @@
         -- we follow the stylish-haskell config file search policy
         -- 1) current directory or its ancestors; 2) home directory
         curdir <- getCurrentDirectory
-        home <- getHomeDirectory
+        -- Ignores home directory when it isn't present.
+        home <- catchIOError ((:[]) <$> getHomeDirectory) (const $ return [])
         b <- doesFileExist ".hlint.yaml"
         implicit <- findM doesFileExist $
             "HLint.hs" : -- the default in HLint 1.*
-            map (</> ".hlint.yaml") (ancestors curdir ++ [home]) -- to match Stylish Haskell
+            map (</> ".hlint.yaml") (ancestors curdir ++ home) -- to match Stylish Haskell
         return $ explicit1 ++ maybeToList implicit ++ explicit2
     where
         ancestors = init . map joinPath . reverse . inits . splitPath
@@ -310,7 +314,7 @@
         f a "Haskell98" = []
         f a ('N':'o':x) | Just x <- readExtension x = delete x a
         f a x | Just x <- readExtension x = x : delete x a
-        f a x = exitMessageImpure $ "Unknown extension: " ++ x
+        f a x = UnknownExtension x : delete (UnknownExtension x) a
 
 
 readExtension :: String -> Maybe Extension
diff --git a/src/Idea.hs b/src/Idea.hs
--- a/src/Idea.hs
+++ b/src/Idea.hs
@@ -11,8 +11,6 @@
 
 import Data.Functor
 import Data.List.Extra
-import Data.Char
-import Numeric
 import HSE.All
 import Config.Type
 import HsColour
@@ -55,13 +53,7 @@
     ,("refactorings", str $ show ideaRefactoring)
     ]
   where
-    str x = "\"" ++ concatMap f x ++ "\""
-        where f '\"' = "\\\""
-              f '\\' = "\\\\"
-              f '\n' = "\\n"
-              f '\r' = "\\r"
-              f x | isControl x || not (isAscii x) = "\\u" ++ takeEnd 4 ("0000" ++ showHex (ord x) "")
-              f x = [x]
+    str x = "\"" ++ escapeJSON x ++ "\""
     dict xs = "{" ++ intercalate "," [show k ++ ":" ++ v | (k,v) <- xs] ++ "}"
     list xs = "[" ++ intercalate "," xs ++ "]"
 
diff --git a/src/Report.hs b/src/Report.hs
--- a/src/Report.hs
+++ b/src/Report.hs
@@ -66,11 +66,3 @@
 writeNote = f . splitOn "`"
     where f (a:b:c) = escapeHTML a ++ "<tt>" ++ escapeHTML b ++ "</tt>" ++ f c
           f xs = concatMap escapeHTML xs
-
-escapeHTML :: String -> String
-escapeHTML = concatMap f
-    where
-        f '>' = "&gt;"
-        f '<' = "&lt;"
-        f '&' = "&amp;"
-        f x = [x]
