diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# v1.0.1.10
+
+## Fixes
+
+- Fixed a socket death during a send (e.g. `EPIPE`/`ECONNRESET`) escaping `Pqi.sendQuery`/`sendQueryParams`/`sendPrepare`/`sendQueryPrepared`/`sendDescribePrepared`/`sendDescribePortal` as a raw, uncaught `IOException` instead of the `False` libpq's `PQsendQuery` and friends always return for a fatal send (marking `PQstatus` `CONNECTION_BAD` and leaving `PQerrorMessage` with the same "server closed the connection unexpectedly" wording used for a connection lost while reading). `Pqi.Native.Transport.send` is `Network.Socket.ByteString.sendAll`, which throws rather than reporting failure through a return value, and `sendAsync` - the function every one of those six calls funnels through - called it with no exception handler at all. This is also the entry point `hasql`'s `Session` machinery actually exercises for every ordinary (non-pipelined) statement, so the escaped exception used to reach `Hasql.Connection.use`'s interruption handling and get treated as an async interruption instead of a classified send failure. `sendAsync` now catches an escaped `IOException`, marks the connection bad via the same `markConnectionLost` classification the read side already had, and returns `False`. The sibling direct sends in `pipelineSync`/`sendFlushRequest` (which bypass `sendAsync` entirely) get the same treatment. Caught by the `pqi-conformance` spec `Pqi.Conformance.Operation.SendQuery.ConnectionLostBeforeSend`.
+
 # v1.0.1.9
 
 ## Fixes
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.9
+version: 1.0.1.10
 category: Database, PostgreSQL
 synopsis: Native (pure-Haskell) adapter for pqi
 description:
diff --git a/src/library/Pqi/Native.hs b/src/library/Pqi/Native.hs
--- a/src/library/Pqi/Native.hs
+++ b/src/library/Pqi/Native.hs
@@ -9,6 +9,7 @@
   )
 where
 
+import Control.Exception (IOException, catch)
 import qualified Data.ByteString as ByteString
 import qualified Data.ByteString.Char8 as ByteString.Char8
 import qualified Data.Map.Strict as Map
@@ -144,12 +145,23 @@
         if pending
           then pure False
           else writeIORef (Connection.pipelineStatus connection) Pqi.PipelineOff $> True,
-      Pqi.pipelineSync = do
-        Connection.sendMessage connection syncMessage
-        modifyIORef' (Connection.pendingSyncs connection) (+ 1)
-        writeIORef (Connection.asyncPending connection) True
-        pure True,
-      Pqi.sendFlushRequest = Connection.sendMessage connection flushMessage $> True,
+      -- Both of these send directly, bypassing 'Query.sendAsync' (there is no
+      -- result-bearing command to track), so they need their own escape
+      -- hatch for the same class of failure 'Query.sendAsync' guards
+      -- against: a socket death mid-send throwing instead of the @False@
+      -- @PQpipelineSync@\/@PQsendFlushRequest@ return on a fatal send.
+      Pqi.pipelineSync =
+        catch
+          do
+            Connection.sendMessage connection syncMessage
+            modifyIORef' (Connection.pendingSyncs connection) (+ 1)
+            writeIORef (Connection.asyncPending connection) True
+            pure True
+          (\err -> False <$ Connection.markConnectionLost connection err),
+      Pqi.sendFlushRequest =
+        catch
+          (Connection.sendMessage connection flushMessage $> True)
+          (\err -> False <$ Connection.markConnectionLost connection err),
       Pqi.getCancel = do
         key <- readIORef (Connection.backendKey connection)
         pure
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
@@ -15,6 +15,7 @@
     fieldValue,
     setError,
     connectionLostMessage,
+    markConnectionLost,
   )
 where
 
@@ -420,6 +421,17 @@
   | 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)
+
+-- | Record an escaped 'IOException' from the transport - a send or a read,
+-- at any point in a flow - the way libpq's own internals do: never throw,
+-- just mark the connection bad with the classified message ('connectionLostMessage'),
+-- so every subsequent call - starting with the one already in flight - sees
+-- it via 'Pqi.status'\/'Pqi.errorMessage'.
+markConnectionLost :: Connection -> IOException -> IO ByteString
+markConnectionLost connection err = do
+  let message = connectionLostMessage err
+  setError connection (message <> "\n")
+  pure message
 
 -- | 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
@@ -77,47 +77,64 @@
 -- | Simple query. Returns the last result, mirroring @PQexec@.
 exec :: Connection -> ByteString -> IO (Maybe NativeResult)
 exec connection sql = withReady connection do
-  sendMessage connection (queryMessage sql)
-  catch (lastMaybe <$> collectSimple connection sql) (fmap Just . connectionLostResult connection sql)
+  catch
+    (sendMessage connection (queryMessage sql) >> (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)
 execParams connection sql params resultFormat
   | tooManyParams params = pure Nothing
   | otherwise = withReady connection do
-      sendMessage connection (paramsWrite sql params resultFormat)
-      catch (Just <$> collectExtended connection sql) (fmap Just . connectionLostResult connection sql)
+      catch
+        (sendMessage connection (paramsWrite sql params resultFormat) >> (Just <$> collectExtended connection sql))
+        (fmap Just . connectionLostResult connection sql)
 
 -- | Prepare a named statement.
 prepare :: Connection -> ByteString -> ByteString -> Maybe [Word32] -> IO (Maybe NativeResult)
 prepare connection name sql parameterTypes
   | maybe False tooManyParams parameterTypes = pure Nothing
   | otherwise = withReady connection do
-      sendMessage connection (prepareWrite name sql parameterTypes)
-      catch (Just <$> collectExtended connection sql) (fmap Just . connectionLostResult connection sql)
+      catch
+        (sendMessage connection (prepareWrite name sql parameterTypes) >> (Just <$> collectExtended connection sql))
+        (fmap Just . connectionLostResult connection sql)
 
 -- | Execute a previously prepared statement.
 execPrepared :: Connection -> ByteString -> [Maybe (ByteString, Format)] -> Format -> IO (Maybe NativeResult)
 execPrepared connection name params resultFormat
   | tooManyParams params = pure Nothing
   | otherwise = withReady connection do
-      sendMessage connection (preparedWrite name params resultFormat)
-      catch (Just <$> collectExtended connection "") (fmap Just . connectionLostResult connection "")
+      catch
+        (sendMessage connection (preparedWrite name params resultFormat) >> (Just <$> collectExtended connection ""))
+        (fmap Just . connectionLostResult connection "")
 
 -- * Asynchronous flows
 
 -- | Send a write in async mode, tracking pending commands for pipeline abort.
+--
+-- A socket death mid-send (e.g. @EPIPE@\/@ECONNRESET@) surfaces here as an
+-- escaped 'IOException' from 'Transport.send', which 'sendMessage' does not
+-- catch. Left uncaught, it would blow straight through this function - and
+-- every caller layered on it ('Pqi.Native.sendQuery' etc., 'Hasql.Comms.Send')
+-- - as a raw exception instead of the @False@ that @PQsendQuery@ always
+-- returns for a fatal send. Catching it here and marking the connection bad
+-- keeps the contract: the caller sees a normal failed send, discoverable via
+-- 'Pqi.status', exactly as libpq's own internals never throw and always
+-- record the failure on the connection instead.
 sendAsync :: Connection -> ByteString -> Poker.Write -> IO Bool
 sendAsync connection sql write = do
   status <- readIORef (connStatus connection)
   case status of
-    ConnectionOk -> do
-      sendMessage connection write
-      writeIORef (currentQuery connection) sql
-      writeIORef (asyncPending connection) True
-      pipeStatus <- readIORef (pipelineStatus connection)
-      when (pipeStatus /= PipelineOff) $ modifyIORef' (pendingCommands connection) (+ 1)
-      pure True
+    ConnectionOk ->
+      catch
+        do
+          sendMessage connection write
+          writeIORef (currentQuery connection) sql
+          writeIORef (asyncPending connection) True
+          pipeStatus <- readIORef (pipelineStatus connection)
+          when (pipeStatus /= PipelineOff) $ modifyIORef' (pendingCommands connection) (+ 1)
+          pure True
+        (\err -> False <$ markConnectionLost connection err)
     _ -> pure False
 
 -- | Whether the connection is in pipeline mode.
@@ -432,8 +449,7 @@
 -- 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")
+  message <- markConnectionLost connection err
   pure (NativeResult FatalError [] [] Nothing (Map.singleton 0x4d message) [] sql)
 
 -- accumulator for a result under construction
