diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # ChangeLog for typed-process
 
+## 0.2.13.0
+
+* Format stdout and stderr in `ExitCodeException` assuming they are in
+  UTF-8.  See [#87](https://github.com/fpco/typed-process/pull/87).
+  Thanks to @9999years for the legwork on this change.
+
 ## 0.2.12.0
 
 * Add `getPid`, `exitCodeExceptionWithOutput`,
diff --git a/src/System/Process/Typed/Internal.hs b/src/System/Process/Typed/Internal.hs
--- a/src/System/Process/Typed/Internal.hs
+++ b/src/System/Process/Typed/Internal.hs
@@ -23,9 +23,11 @@
 import Control.Concurrent.STM (newEmptyTMVarIO, atomically, putTMVar, readTMVar, STM, tryPutTMVar, throwSTM)
 import System.Exit (ExitCode)
 import qualified Data.ByteString.Lazy as L
-import qualified Data.ByteString.Lazy.Char8 as L8
 import Data.String (IsString (fromString))
 import Control.Monad.IO.Unlift
+import qualified Data.Text.Encoding.Error as TEE
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TLE
 
 #if MIN_VERSION_process(1, 4, 0) && !WINDOWS
 import System.Posix.Types (GroupID, UserID)
@@ -620,11 +622,15 @@
         , show (eceProcessConfig ece) { pcEnv = Nothing }
         , if L.null (eceStdout ece)
             then ""
-            else "Standard output:\n\n" ++ L8.unpack (eceStdout ece)
+            else "Standard output:\n\n" ++ unpack (eceStdout ece)
         , if L.null (eceStderr ece)
             then ""
-            else "Standard error:\n\n" ++ L8.unpack (eceStderr ece)
+            else "Standard error:\n\n" ++ unpack (eceStderr ece)
         ]
+      where
+        -- Format with UTF-8, because we have to choose some encoding,
+        -- and UTF-8 is the least likely to be wrong in general.
+        unpack = TL.unpack . TLE.decodeUtf8With TEE.lenientDecode
 
 -- | Wrapper for when an exception is thrown when reading from a child
 -- process, used by 'byteStringOutput'.
diff --git a/typed-process.cabal b/typed-process.cabal
--- a/typed-process.cabal
+++ b/typed-process.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.37.0.
+-- This file has been generated from package.yaml by hpack version 0.38.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           typed-process
-version:        0.2.12.0
+version:        0.2.13.0
 synopsis:       Run external processes, with strong typing of streams
 description:    Please see the tutorial at <https://github.com/fpco/typed-process#readme>
 category:       System
@@ -38,6 +38,7 @@
     , bytestring
     , process >=1.2
     , stm
+    , text
     , transformers
     , unliftio-core
   default-language: Haskell2010
@@ -64,6 +65,7 @@
     , process >=1.2
     , stm
     , temporary
+    , text
     , transformers
     , typed-process
     , unliftio-core
@@ -88,6 +90,7 @@
     , process >=1.2
     , stm
     , temporary
+    , text
     , transformers
     , typed-process
     , unliftio-core
