diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## Version 1.8.0
+
+* BREAKING CHANGE: Remove `Exception` instance for `TLSError`.
+  The library now throws `TLSException` only.
+  If you need to change your code, please refer to
+  [this example](https://github.com/snoyberg/http-client/commit/73d1a4eb451c089878ba95e96371d0b18287ffb8) first.
+  [#457](https://github.com/haskell-tls/hs-tls/pull/457)
+
 ## Version 1.7.1
 
 * NOP on UserCanceled event
diff --git a/Network/TLS.hs b/Network/TLS.hs
--- a/Network/TLS.hs
+++ b/Network/TLS.hs
@@ -31,6 +31,9 @@
     , recvData
     , bye
 
+    -- * Exceptions
+    -- $exceptions
+
     -- * Backend abstraction
     , HasBackend(..)
     , Backend(..)
@@ -198,3 +201,10 @@
 --   both cases of full-negotiation and resumption.
 getClientCertificateChain :: Context -> IO (Maybe CertificateChain)
 getClientCertificateChain ctx = usingState_ ctx S.getClientCertificateChain
+
+{- $exceptions
+    Since 1.8.0, this library only throws exceptions of type 'TLSException'.
+    In the common case where the chosen backend is socket, 'IOException'
+    may be thrown as well. This happens because the backend for sockets,
+    opaque to most modules in the @tls@ library, throws those exceptions.
+-}
diff --git a/Network/TLS/Context/Internal.hs b/Network/TLS/Context/Internal.hs
--- a/Network/TLS/Context/Internal.hs
+++ b/Network/TLS/Context/Internal.hs
@@ -234,7 +234,7 @@
 withLog ctx f = ctxWithHooks ctx (f . hookLogging)
 
 throwCore :: MonadIO m => TLSError -> m a
-throwCore = liftIO . throwIO
+throwCore = liftIO . throwIO . Uncontextualized
 
 failOnEitherError :: MonadIO m => m (Either TLSError a) -> m a
 failOnEitherError f = do
@@ -255,7 +255,7 @@
 usingHState :: MonadIO m => Context -> HandshakeM a -> m a
 usingHState ctx f = liftIO $ modifyMVar (ctxHandshake ctx) $ \mst ->
     case mst of
-        Nothing -> throwCore $ Error_Misc "missing handshake"
+        Nothing -> liftIO $ throwIO $ MissingHandshake
         Just st -> return $ swap (Just <$> runHandshake st f)
 
 getHState :: MonadIO m => Context -> m (Maybe HandshakeState)
diff --git a/Network/TLS/Handshake/Common.hs b/Network/TLS/Handshake/Common.hs
--- a/Network/TLS/Handshake/Common.hs
+++ b/Network/TLS/Handshake/Common.hs
@@ -58,7 +58,12 @@
 
 handleException :: Context -> IO () -> IO ()
 handleException ctx f = catchException f $ \exception -> do
-    let tlserror = fromMaybe (Error_Misc $ show exception) $ fromException exception
+    -- If the error was an Uncontextualized TLSException, we replace the
+    -- context with HandshakeFailed. If it's anything else, we convert
+    -- it to a string and wrap it with Error_Misc and HandshakeFailed.
+    let tlserror = case fromException exception of
+          Just e | Uncontextualized e' <- e -> e'
+          _ -> Error_Misc (show exception)
     setEstablished ctx NotEstablished
     handle ignoreIOErr $ do
         tls13 <- tls13orLater ctx
diff --git a/Network/TLS/IO.hs b/Network/TLS/IO.hs
--- a/Network/TLS/IO.hs
+++ b/Network/TLS/IO.hs
@@ -26,7 +26,6 @@
 import Control.Monad.State.Strict
 import qualified Data.ByteString as B
 import Data.IORef
-import System.IO.Error (mkIOError, eofErrorType)
 
 import Network.TLS.Context.Internal
 import Network.TLS.Hooks
@@ -172,7 +171,7 @@
     established <- ctxEstablished ctx
     when (established == NotEstablished) $ throwIO ConnectionNotEstablished
     eofed <- ctxEOF ctx
-    when eofed $ throwIO $ mkIOError eofErrorType "data" Nothing Nothing
+    when eofed $ throwIO $ PostHandshake Error_EOF
 
 ----------------------------------------------------------------
 
diff --git a/Network/TLS/Parameters.hs b/Network/TLS/Parameters.hs
--- a/Network/TLS/Parameters.hs
+++ b/Network/TLS/Parameters.hs
@@ -384,7 +384,7 @@
       -- | A collection of trust anchors to be used by a client as
       -- part of validation of server certificates.  This is set as
       -- first argument to function 'onServerCertificate'.  Package
-      -- <https://hackage.haskell.org/package/x509-system x509-system>
+      -- <https://hackage.haskell.org/package/crypton-x509-system crypton-x509-system>
       -- gives access to a default certificate store configured in the
       -- system.
       --
diff --git a/Network/TLS/Struct.hs b/Network/TLS/Struct.hs
--- a/Network/TLS/Struct.hs
+++ b/Network/TLS/Struct.hs
@@ -156,7 +156,11 @@
     | ProtocolType_DeprecatedHandshake
     deriving (Eq, Show)
 
--- | TLSError that might be returned through the TLS stack
+-- | TLSError that might be returned through the TLS stack.
+--
+-- Prior to version 1.8.0, this type had an @Exception@ instance.
+-- In version 1.8.0, this instance was removed, and functions in
+-- this library now only throw 'TLSException'.
 data TLSError =
       Error_Misc String        -- ^ mainly for instance of Error
     | Error_Protocol (String, Bool, AlertDescription)
@@ -168,16 +172,29 @@
     | Error_Packet_Parsing String
     deriving (Eq, Show, Typeable)
 
-instance Exception TLSError
-
--- | TLS Exceptions related to bad user usage or
--- asynchronous errors
+-- | TLS Exceptions. Some of the data constructors indicate incorrect use of
+--   the library, and the documentation for those data constructors calls
+--   this out. The others wrap 'TLSError' with some kind of context to explain
+--   when the exception occurred.
 data TLSException =
-      Terminated Bool String TLSError -- ^ Early termination exception with the reason
-                                      --   and the error associated
-    | HandshakeFailed TLSError        -- ^ Handshake failed for the reason attached
-    | ConnectionNotEstablished        -- ^ Usage error when the connection has not been established
-                                      --   and the user is trying to send or receive data
+      Terminated Bool String TLSError
+      -- ^ Early termination exception with the reason and the error associated
+    | HandshakeFailed TLSError
+      -- ^ Handshake failed for the reason attached.
+    | PostHandshake TLSError
+      -- ^ Failure occurred while sending or receiving data after the
+      --   TLS handshake succeeded.
+    | Uncontextualized TLSError
+      -- ^ Lifts a 'TLSError' into 'TLSException' without provided any context
+      --   around when the error happened.
+    | ConnectionNotEstablished
+      -- ^ Usage error when the connection has not been established
+      --   and the user is trying to send or receive data.
+      --   Indicates that this library has been used incorrectly. 
+    | MissingHandshake
+      -- ^ Expected that a TLS handshake had already taken place, but no TLS
+      --   handshake had occurred.
+      --   Indicates that this library has been used incorrectly. 
     deriving (Show,Eq,Typeable)
 
 instance Exception TLSException
diff --git a/tls.cabal b/tls.cabal
--- a/tls.cabal
+++ b/tls.cabal
@@ -1,13 +1,13 @@
 cabal-version:      >=1.10
 name:               tls
-version:            1.7.1
+version:            1.8.0
 license:            BSD3
 license-file:       LICENSE
 copyright:          Vincent Hanquez <vincent@snarc.org>
 maintainer:         Kazu Yamamoto <kazu@iij.ad.jp>
 author:             Vincent Hanquez <vincent@snarc.org>
 stability:          experimental
-homepage:           http://github.com/vincenthz/hs-tls
+homepage:           https://github.com/haskell-tls/hs-tls
 synopsis:           TLS/SSL protocol native implementation (Server and Client)
 description:
     Native Haskell TLS and SSL protocol implementation for server and client.
@@ -31,7 +31,7 @@
 
 source-repository head
     type:     git
-    location: https://github.com/vincenthz/hs-tls
+    location: https://github.com/haskell-tls/hs-tls
     subdir:   core
 
 flag compat
