diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for typed-protocols
 
+## 1.2.1.0 -- 2026-04-16
+
+* Support GHC-9.14, io-classes >=1.8 && < 1.11
+
 ## 1.2.0.0 -- 2025-02-05
 
 * Make `runPeerWithDriver` strict, it evaluates the result and `dstate` to
diff --git a/examples/Network/TypedProtocol/Driver/Simple.hs b/examples/Network/TypedProtocol/Driver/Simple.hs
--- a/examples/Network/TypedProtocol/Driver/Simple.hs
+++ b/examples/Network/TypedProtocol/Driver/Simple.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP                  #-}
 {-# LANGUAGE TypeFamilies         #-}
 -- @UndecidableInstances@ extensions is required for defining @Show@ instance
 -- of @'TraceSendRecv'@.
@@ -175,14 +176,17 @@
 -- | Run a codec incremental decoder 'DecodeStep' against a channel. It also
 -- takes any extra input data and returns any unused trailing data.
 --
-runDecoderWithChannel :: ( Monad m
-                         , MonadEvaluate m
-                         , NFData failure
-                         )
-                      => Channel m bytes
-                      -> Maybe bytes
-                      -> DecodeStep bytes failure m a
-                      -> m (Either failure (a, Maybe bytes))
+runDecoderWithChannel
+  :: ( MonadEvaluate m
+#if !MIN_VERSION_io_classes(1,10,0)
+     , Monad m
+#endif
+     , NFData failure
+     )
+  => Channel m bytes
+  -> Maybe bytes
+  -> DecodeStep bytes failure m a
+  -> m (Either failure (a, Maybe bytes))
 
 runDecoderWithChannel Channel{recv} = go
   where
diff --git a/examples/Network/TypedProtocol/PingPong/Codec.hs b/examples/Network/TypedProtocol/PingPong/Codec.hs
--- a/examples/Network/TypedProtocol/PingPong/Codec.hs
+++ b/examples/Network/TypedProtocol/PingPong/Codec.hs
@@ -31,6 +31,8 @@
             DecodeDone (SomeMessage MsgPing) trailing
           (SingIdle, "done") ->
             DecodeDone (SomeMessage MsgDone) trailing
+          (SingDone, _) ->
+            notActiveState stok
 
           (_       , _     ) -> DecodeFail failure
             where failure = CodecFailure ("unexpected server message: " ++ str)
diff --git a/examples/Network/TypedProtocol/ReqResp/Codec.hs b/examples/Network/TypedProtocol/ReqResp/Codec.hs
--- a/examples/Network/TypedProtocol/ReqResp/Codec.hs
+++ b/examples/Network/TypedProtocol/ReqResp/Codec.hs
@@ -40,6 +40,8 @@
           (SingBusy, ("MsgResp", str'))
             | Just resp <- readMaybe str'
             -> DecodeDone (SomeMessage (MsgResp resp)) trailing
+          (SingDone, _) ->
+            notActiveState stok
 
           (_       , _     ) -> DecodeFail failure
             where failure = CodecFailure ("unexpected server message: " ++ str)
@@ -101,6 +103,8 @@
             -> DecodeDone (Annotator \str'' ->
                            let used = init $ drop 8 str'' in
                            SomeMessage (MsgResp (WithBytes used resp))) trailing
+          (SingDone, _) ->
+            notActiveState stok
 
           (_       , _     ) -> DecodeFail failure
             where failure = CodecFailure ("unexpected server message: " ++ str)
@@ -145,5 +149,5 @@
               (SingBusy, _) ->
                 DecodeFail failure
                   where failure = CodecFailure ("unexpected server message: " ++ show msg)
-
-              (a@SingDone, _) -> notActiveState a
+              (SingDone, _) ->
+                notActiveState stok
diff --git a/examples/Network/TypedProtocol/Stateful/ReqResp/Codec.hs b/examples/Network/TypedProtocol/Stateful/ReqResp/Codec.hs
--- a/examples/Network/TypedProtocol/Stateful/ReqResp/Codec.hs
+++ b/examples/Network/TypedProtocol/Stateful/ReqResp/Codec.hs
@@ -36,8 +36,7 @@
     encode (StateBusy req) (MsgResp resp) = "MsgResp " ++ encodeResp req resp ++ "\n"
 
     decode :: forall (st :: ReqResp req).
-              ActiveState st
-           => StateToken st
+              StateToken st
            -> State st
            -> m (DecodeStep String CodecFailure m (SomeMessage st))
     decode stok state =
diff --git a/src/Network/TypedProtocol/Driver.hs b/src/Network/TypedProtocol/Driver.hs
--- a/src/Network/TypedProtocol/Driver.hs
+++ b/src/Network/TypedProtocol/Driver.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP          #-}
 {-# LANGUAGE TypeFamilies #-}
 
 -- | Actions for running 'Peer's with a 'Driver'
@@ -124,8 +125,12 @@
 --
 runPeerWithDriver
   :: forall ps (st :: ps) pr dstate m a.
+#if MIN_VERSION_io_classes(1,10,0)
+     ( MonadEvaluate m
+#else
      ( Monad m
      , MonadEvaluate m
+#endif
      , NFData a
      )
   => Driver ps pr dstate m
diff --git a/stateful/Network/TypedProtocol/Stateful/Driver.hs b/stateful/Network/TypedProtocol/Stateful/Driver.hs
--- a/stateful/Network/TypedProtocol/Stateful/Driver.hs
+++ b/stateful/Network/TypedProtocol/Stateful/Driver.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 -- | Actions for running 'Peer's with a 'Driver'.  This module should be
 -- imported qualified.
 --
@@ -12,7 +14,9 @@
   ) where
 
 import Control.DeepSeq (NFData, force)
+#if !MIN_VERSION_io_classes(1,10,0)
 import Control.Monad.Class.MonadSTM
+#endif
 import Control.Monad.Class.MonadThrow
 
 import Data.Kind (Type)
@@ -85,7 +89,9 @@
 runPeerWithDriver
   :: forall ps (st :: ps) pr bytes failure dstate (f :: ps -> Type) m a.
      ( MonadEvaluate m
+#if !MIN_VERSION_io_classes(1,10,0)
      , MonadSTM m
+#endif
      , NFData a
      )
   => Driver ps pr bytes failure dstate f m
diff --git a/typed-protocols.cabal b/typed-protocols.cabal
--- a/typed-protocols.cabal
+++ b/typed-protocols.cabal
@@ -1,6 +1,6 @@
 cabal-version:       3.4
 name:                typed-protocols
-version:             1.2.0.0
+version:             1.2.1.0
 synopsis:            A framework for strongly typed protocols
 description:         A robust session type framework which supports protocol pipelining.
                      Haddocks are published [here](https://input-output-hk.github.io/typed-protocols/)
@@ -11,7 +11,7 @@
 maintainer:          alex@well-typed.com, duncan@well-typed.com, marcin.szamotulski@iohk.io
 category:            Control
 build-type:          Simple
-tested-with:         GHC == {9.6, 9.8, 9.10, 9.12}
+tested-with:         GHC == {9.6, 9.8, 9.10, 9.12, 9.14}
 extra-doc-files:     CHANGELOG.md
                      README.md
 
@@ -31,6 +31,11 @@
                      -Wredundant-constraints
                      -Wunused-packages
 
+  -- In ghc-9.14 the `pattern` namespace specifier is deprecated.
+  if impl(ghc >=9.14)
+    ghc-options:
+      -Wno-pattern-namespace-specifier
+
 library
   import:             GHC
   exposed-modules:    Network.TypedProtocol
@@ -42,9 +47,9 @@
                     , Network.TypedProtocol.Driver
                     , Network.TypedProtocol.Proofs
   other-modules:      Network.TypedProtocol.Lemmas
-  build-depends:      base >=4.12 && <4.22,
+  build-depends:      base >=4.12 && <4.23,
                       deepseq,
-                      io-classes:io-classes ^>= 1.8,
+                      io-classes:io-classes ^>= 1.8 || ^>= 1.9 || ^>= 1.10,
                       singletons ^>= 3.0
   hs-source-dirs:     src
   default-extensions: DataKinds
@@ -56,7 +61,7 @@
   exposed-modules:    Network.TypedProtocol.Codec.Properties
                       Network.TypedProtocol.Stateful.Codec.Properties
   other-modules:      Test.QuickCheck.Monoids.Compat
-  build-depends:      base >=4.12 && <4.22,
+  build-depends:      base >=4.12 && <4.23,
                       typed-protocols:{stateful, typed-protocols},
                       QuickCheck
   hs-source-dirs:     properties
