diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,18 @@
+# v1.0.1.9
+
+## Fixes
+
+- Fixed a DNS resolution failure during `connectdb` reporting the raw `Show`n `Network.Socket.getAddrInfo` exception (e.g. `could not connect to server: Network.Socket.getAddrInfo (called with preferred socket type/protocol: ...): does not exist (nodename nor servname provided, or not known)`) instead of libpq's own sentence for it (`could not translate host name "..." to address: nodename nor servname provided, or not known`). `connectFailureMessage` now recognizes a resolver failure by `Network.Socket.getAddrInfo` naming itself in the exception's `ioe_location`, and reproduces libpq's wording using the exception's `ioe_description`. Caught by the `pqi-conformance` spec `Pqi.Conformance.Operation.Connectdb.UnresolvableHost`.
+
+- Fixed a handshake-time hard TCP reset (`ECONNRESET`, as opposed to a clean EOF) reporting the raw `Show`n `IOException` (e.g. `Network.Socket.recvBuf: resource vanished (Connection reset by peer)`) instead of libpq's own "server closed the connection unexpectedly" sentence, which it uses for both a reset and a clean EOF alike. `handshakeFailureMessage`'s classification (`isConnectionLost`, factored out as `connectionLostMessage`) now also recognizes a reset - `Network.Socket` surfaces `ECONNRESET` as `ioe_type == ResourceVanished` rather than `System.IO.Error.eofErrorType` - not just a clean EOF. Caught by the `pqi-conformance` spec `Pqi.Conformance.Operation.Connectdb.HandshakeReset`.
+
+- Fixed a connection reset while a query response was in flight escaping `Pqi.exec`/`execParams`/`prepare`/`execPrepared`/`describePrepared`/`describePortal` as a raw, uncaught `IOException` instead of coming back as a classified `FatalError` result the way libpq's `PQexec` does (a lost connection mid-query never throws there; it reports a result with `FatalError` status and the same "server closed the connection unexpectedly" wording used for a handshake-time loss). Each of those six flows now catches an `IOException` escaping its read loop and reports it through the same `connectionLostMessage` classification, also marking the connection `ConnectionBad`. Caught by the `pqi-conformance` spec `Pqi.Conformance.Operation.Exec.ConnectionLostMidQuery`. Found via `hasql` issue #329.
+
 # v1.0.1.8
 
 ## Fixes
 
-- Fixed `connectFailureMessage` (used when the initial `connect(2)` fails, e.g. a missing Unix-socket directory) hand-rolling a TCP-shaped message - the raw `Show`n `IOException` prefixed with `"could not connect to server: "` and a `(Unix domain socket '<path>')` parenthetical appended - instead of reporting the failure the way libpq does. That hand-rolled text retained the literal prefix `"could not connect to server: "`, which is also the substring `Hasql.Connection`'s error classifier matches to identify a transient networking failure - so a permanent misconfiguration (missing socket directory) was misclassified as transient. The Unix-socket branch now delegates to `unixSocketFailureMessage`, extracting the underlying `IOException`'s `ioe_description` (the raw OS `strerror` text, e.g. `"No such file or directory"`) instead of embedding its whole `Show`n form, and appending the same `"Is the server running locally and accepting connections on that socket?"` hint libpq appends for this failure - matching libpq's message for this case byte-for-byte. Also fixed `unixSocketFailureMessage` itself quoting the socket path with single quotes (`'<path>'`) instead of libpq's double quotes (`"<path>"`), which affects every message it formats, including the handshake-rejection path this Unix-socket branch now shares. Caught by the `pqi-conformance` spec `Pqi.Conformance.Operation.Connectdb.MissingUnixSocketDirectory`. Found via `hasql` issue #329.
+- Fixed `connectFailureMessage` (used when the initial `connect(2)` fails, e.g. a missing Unix-socket directory) hand-rolling a TCP-shaped message - the raw `Show`n `IOException` prefixed with `"could not connect to server: "` and a `(Unix domain socket '<path>')` parenthetical appended - instead of reporting the failure the way libpq does. That hand-rolled text retained the literal prefix `"could not connect to server: "`, which is also the substring `Hasql.Connection`'s error classifier matches to identify a transient networking failure - so a permanent misconfiguration (missing socket directory) was misclassified as transient. The Unix-socket branch now delegates to `unixSocketFailureMessage`, extracting the underlying `IOException`'s `ioe_description` (the raw OS `strerror` text, e.g. `"No such file or directory"`) instead of embedding its whole `Show`n form, and appending the same `"Is the server running locally and accepting connections on that socket?"` hint libpq appends for this failure - matching libpq's message for this case exactly. Also fixed `unixSocketFailureMessage` itself quoting the socket path with single quotes (`'<path>'`) instead of libpq's double quotes (`"<path>"`), which affects every message it formats, including the handshake-rejection path this Unix-socket branch now shares. Caught by the `pqi-conformance` spec `Pqi.Conformance.Operation.Connectdb.MissingUnixSocketDirectory`. Found via `hasql` issue #329.
 
 # v1.0.1.7
 
diff --git a/pqi-native.cabal b/pqi-native.cabal
--- a/pqi-native.cabal
+++ b/pqi-native.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: pqi-native
-version: 1.0.1.8
+version: 1.0.1.9
 category: Database, PostgreSQL
 synopsis: Native (pure-Haskell) adapter for pqi
 description:
@@ -11,7 +11,7 @@
   @ptr-peeker@; the public library is an abstraction over it that builds the
   @pqi@ @Adapter@.
 
-  __Status: Alpha.__ Verified byte-for-byte against @postgresql-libpq@ via a
+  __Status: Alpha.__ Verified exactly against @postgresql-libpq@ via a
   differential conformance suite, but not yet proven in production. It
   implements the same @pqi@ interface as
   [@pqi-ffi@](https://hackage.haskell.org/package/pqi-ffi), the stable
@@ -158,5 +158,5 @@
   build-depends:
     base >=4.11 && <5,
     hspec >=2.11 && <2.12,
-    pqi-conformance ^>=1.0.8,
+    pqi-conformance ^>=1.0.9,
     pqi-native,
diff --git a/src/library/Pqi/Native/Connection.hs b/src/library/Pqi/Native/Connection.hs
--- a/src/library/Pqi/Native/Connection.hs
+++ b/src/library/Pqi/Native/Connection.hs
@@ -14,16 +14,18 @@
     sendMessage,
     fieldValue,
     setError,
+    connectionLostMessage,
   )
 where
 
 import Control.Exception (IOException, SomeException, catch, try)
 import qualified Data.ByteString as ByteString
 import qualified Data.ByteString.Char8 as ByteString.Char8
+import Data.List (isInfixOf)
 import qualified Data.Map.Strict as Map
 import qualified Data.Sequence as Seq
 import qualified Data.Set as Set
-import GHC.IO.Exception (ioe_description)
+import GHC.IO.Exception (IOErrorType (ResourceVanished), ioe_description, ioe_location, ioe_type)
 import Pqi (ConnStatus (..), Notify (..), PipelineStatus (..), Verbosity (..))
 import qualified Pqi.Native.Auth as Auth
 import Pqi.Native.Prelude
@@ -357,7 +359,8 @@
   writeIORef (connStatus connection) ConnectionBad
 
 -- | Format an initial-connect failure (the socket couldn't even be opened),
--- matching libpq's distinct phrasing for a Unix-domain socket vs. a TCP host.
+-- matching libpq's distinct phrasing for a Unix-domain socket, a DNS
+-- resolution failure, and any other TCP connect failure.
 connectFailureMessage :: ConnInfo -> IOException -> ByteString
 connectFailureMessage connInfo err
   | Transport.isUnixSocketHost (host connInfo) =
@@ -366,6 +369,17 @@
         ( ByteString.Char8.pack (ioe_description err)
             <> "\n\tIs the server running locally and accepting connections on that socket?\n"
         )
+  -- 'Network.Socket.getAddrInfo' names itself in 'ioe_location' on failure
+  -- (there is no other reliable way to tell a resolver failure apart from a
+  -- 'Network.Socket.connect' failure once both have collapsed to a plain
+  -- 'IOException'), and libpq has its own distinct sentence for this case
+  -- rather than the generic "could not connect to server".
+  | "getAddrInfo" `isInfixOf` ioe_location err =
+      "could not translate host name \""
+        <> host connInfo
+        <> "\" to address: "
+        <> ByteString.Char8.pack (ioe_description err)
+        <> "\n"
   | otherwise = "could not connect to server: " <> ByteString.Char8.pack (show err)
 
 -- | Format a handshake-time 'IOException' - e.g. the server closing the
@@ -375,17 +389,37 @@
 -- 'tcpFailureMessage' wrapper 'failWith' uses for a rejected 'ErrorResponse',
 -- so a failure that interrupts the handshake reads exactly like any other
 -- classified rejection instead of escaping 'establish' as an uncaught
--- exception. An EOF (the frame never completing) gets libpq's own wording for
--- it; any other handshake-time I\/O error falls back to its 'show'n form.
+-- exception. A connection lost outright - a clean EOF or a hard TCP reset -
+-- gets libpq's own wording for it (see 'connectionLostMessage'); any other
+-- handshake-time I\/O error falls back to its 'show'n form.
 handshakeFailureMessage :: Connection -> ConnInfo -> IOException -> IO ByteString
 handshakeFailureMessage connection connInfo err = do
   let fmtFields
-        | isEOFError err =
-            "server closed the connection unexpectedly\n\tThis probably means the server terminated abnormally\n\tbefore or while processing the request.\n"
-        | otherwise = ByteString.Char8.pack (show err)
+        | isConnectionLost err = connectionLostMessage err <> "\n"
+        | otherwise = connectionLostMessage err
   if Transport.isUnixSocketHost (host connInfo)
     then pure (unixSocketFailureMessage connInfo fmtFields)
     else tcpFailureMessage connection connInfo fmtFields
+
+-- | Whether an 'IOException' represents the connection being lost outright -
+-- a clean EOF (the frame never completing) or a hard TCP reset
+-- (@ECONNRESET@, which 'Network.Socket' surfaces as 'ResourceVanished'
+-- rather than 'System.IO.Error.eofErrorType') - as opposed to some other kind
+-- of I\/O failure.
+isConnectionLost :: IOException -> Bool
+isConnectionLost err = isEOFError err || ioe_type err == ResourceVanished
+
+-- | libpq's own wording for a connection lost outright (see
+-- 'isConnectionLost'), without a trailing newline - callers that embed this
+-- inline (e.g. 'handshakeFailureMessage') append one themselves; the one that
+-- folds it into a result's error fields ('Pqi.Native.Query') gets its
+-- trailing newline for free from 'Pqi.Native.Types.formatResultError'. Falls
+-- back to the exception's 'show'n form for anything else.
+connectionLostMessage :: IOException -> ByteString
+connectionLostMessage err
+  | isConnectionLost err =
+      "server closed the connection unexpectedly\n\tThis probably means the server terminated abnormally\n\tbefore or while processing the request."
+  | otherwise = ByteString.Char8.pack (show err)
 
 -- | The handshake-failure message ('failWith', inside 'handshake') for a
 -- Unix-domain socket connection: names the socket path rather than a
diff --git a/src/library/Pqi/Native/Query.hs b/src/library/Pqi/Native/Query.hs
--- a/src/library/Pqi/Native/Query.hs
+++ b/src/library/Pqi/Native/Query.hs
@@ -17,7 +17,7 @@
   )
 where
 
-import Control.Exception (mask_)
+import Control.Exception (IOException, catch, mask_)
 import qualified Data.Map.Strict as Map
 import qualified Data.Sequence as Seq
 import Pqi (ConnStatus (..), ExecStatus (..), Format (..), PipelineStatus (..))
@@ -78,7 +78,7 @@
 exec :: Connection -> ByteString -> IO (Maybe NativeResult)
 exec connection sql = withReady connection do
   sendMessage connection (queryMessage sql)
-  lastMaybe <$> collectSimple connection sql
+  catch (lastMaybe <$> collectSimple connection sql) (fmap Just . connectionLostResult connection sql)
 
 -- | Parameterized query via the extended protocol.
 execParams :: Connection -> ByteString -> [Maybe (Word32, ByteString, Format)] -> Format -> IO (Maybe NativeResult)
@@ -86,7 +86,7 @@
   | tooManyParams params = pure Nothing
   | otherwise = withReady connection do
       sendMessage connection (paramsWrite sql params resultFormat)
-      Just <$> collectExtended connection sql
+      catch (Just <$> collectExtended connection sql) (fmap Just . connectionLostResult connection sql)
 
 -- | Prepare a named statement.
 prepare :: Connection -> ByteString -> ByteString -> Maybe [Word32] -> IO (Maybe NativeResult)
@@ -94,7 +94,7 @@
   | maybe False tooManyParams parameterTypes = pure Nothing
   | otherwise = withReady connection do
       sendMessage connection (prepareWrite name sql parameterTypes)
-      Just <$> collectExtended connection sql
+      catch (Just <$> collectExtended connection sql) (fmap Just . connectionLostResult connection sql)
 
 -- | Execute a previously prepared statement.
 execPrepared :: Connection -> ByteString -> [Maybe (ByteString, Format)] -> Format -> IO (Maybe NativeResult)
@@ -102,7 +102,7 @@
   | tooManyParams params = pure Nothing
   | otherwise = withReady connection do
       sendMessage connection (preparedWrite name params resultFormat)
-      Just <$> collectExtended connection ""
+      catch (Just <$> collectExtended connection "") (fmap Just . connectionLostResult connection "")
 
 -- * Asynchronous flows
 
@@ -381,13 +381,13 @@
 describePrepared :: Connection -> ByteString -> IO (Maybe NativeResult)
 describePrepared connection name = withReady connection do
   sendMessage connection (describeStatementMessage name <> syncMessage)
-  Just <$> collectExtended connection ""
+  catch (Just <$> collectExtended connection "") (fmap Just . connectionLostResult connection "")
 
 -- | Describe a portal.
 describePortal :: Connection -> ByteString -> IO (Maybe NativeResult)
 describePortal connection name = withReady connection do
   sendMessage connection (describePortalMessage name <> syncMessage)
-  Just <$> collectExtended connection ""
+  catch (Just <$> collectExtended connection "") (fmap Just . connectionLostResult connection "")
 
 -- * Parameter projections
 
@@ -423,6 +423,18 @@
   case status of
     ConnectionOk -> action
     _ -> pure Nothing
+
+-- | Turn a read loop's escaped 'IOException' - e.g. a connection reset while
+-- a result is still in flight - into a classified 'FatalError' result,
+-- matching @PQexec@: libpq never throws here, it reports the same
+-- "server closed the connection unexpectedly" wording it uses for a
+-- handshake-time loss (see 'connectionLostMessage'), and marks the
+-- connection bad so the caller's next call sees it too.
+connectionLostResult :: Connection -> ByteString -> IOException -> IO NativeResult
+connectionLostResult connection sql err = do
+  let message = connectionLostMessage err
+  setError connection (message <> "\n")
+  pure (NativeResult FatalError [] [] Nothing (Map.singleton 0x4d message) [] sql)
 
 -- accumulator for a result under construction
 data Builder = Builder
diff --git a/src/transport/Pqi/Native/Transport.hs b/src/transport/Pqi/Native/Transport.hs
--- a/src/transport/Pqi/Native/Transport.hs
+++ b/src/transport/Pqi/Native/Transport.hs
@@ -104,8 +104,8 @@
 -- as needed. Throws on EOF before @n@ bytes are available.
 --
 -- The wait for bytes is deliberately left interruptible. Nothing has been
--- consumed at this point, so a caller that gives up here loses nothing - and,
--- crucially, is /able/ to give up. A caller blocked on a message the server
+-- consumed at this point, so a caller that gives up here loses nothing - and
+-- is /able/ to give up. A caller blocked on a message the server
 -- will never send (an aborted pipeline whose bookkeeping has drifted, say)
 -- must stay abandonable by 'System.Timeout.timeout'; masking the wait
 -- uninterruptibly turns that stall into a deadlock no timer can break.
