This seems to be a difference between the strict and lazy modules.
import qualified Data.ByteString.Char8 as Bc8
import qualified Data.ByteString.Lazy as Bl
import qualified Data.Text as T
import qualified Data.Text.Lazy as Tl
main :: IO ()
main = do
let bad = Bc8.pack ['\x6e', '\x64', '\x72', '\x65', '\x73', '\x20', '\x4c', '\xf6', '\x68', '\x2c', '\x20', '\x46', '\x72', '\x61', '\x6e', '\x6b']
-- prints "ndres Lh, Frank"
print (T.decodeUtf8With T.ignore bad)
-- prints "ndres L\65533h, Frank"
print (Tl.unpack (Tl.decodeUtf8With T.lenientDecode (Bl.fromStrict bad)))
-- hangs
print (Tl.unpack (Tl.decodeUtf8With T.ignore (Bl.fromStrict bad)))
This seems to be a difference between the strict and lazy modules.