diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.0.9.0
+
+* Add `instance Handle IOE`
+
+* Add `rethrowIO`
+
 ## 0.0.8.0
 
 Add `Consume`, `await`, `consumeStream`, `zipCoroutines`,
diff --git a/bluefin-internal.cabal b/bluefin-internal.cabal
--- a/bluefin-internal.cabal
+++ b/bluefin-internal.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               bluefin-internal
-version:            0.0.8.0
+version:            0.0.9.0
 license:            MIT
 license-file:       LICENSE
 author:             Tom Ellis
@@ -77,7 +77,7 @@
     default-language: Haskell2010
     hs-source-dirs: src
     build-depends:
-      async,
+      async >= 2.2 && < 2.3,
       base >= 4.12 && < 4.21,
       unliftio-core < 0.3,
       transformers < 0.7,
diff --git a/src/Bluefin/Internal.hs b/src/Bluefin/Internal.hs
--- a/src/Bluefin/Internal.hs
+++ b/src/Bluefin/Internal.hs
@@ -243,7 +243,7 @@
 insertFirst = weakenEff (drop (eq (# #)))
 
 insertSecond :: Eff (c1 :& b) r -> Eff (c1 :& (c2 :& b)) r
-insertSecond = weakenEff (b (drop (eq (# #))))
+insertSecond = insertManySecond
 
 insertManySecond :: (b :> c) => Eff (c1 :& b) r -> Eff (c1 :& c) r
 insertManySecond = weakenEff (bimap has has)
@@ -355,6 +355,9 @@
 instance Handle (Writer w) where
   mapHandle (Writer wr) = Writer (mapHandle wr)
 
+instance Handle IOE where
+  mapHandle MkIOE = MkIOE
+
 newtype In (a :: Effects) (b :: Effects) = In# (# #)
 
 merge :: (# #) -> (a :& a) `In` a
@@ -489,6 +492,51 @@
   (exn -> Eff es a) ->
   Eff es a
 catch f h = handle h f
+
+-- We really do need to have an IOE argument here because, it is not
+-- determined which of Ex1 or Ex2 is produced in the following code,
+-- due to pure exceptions being imprecise.
+--
+-- f :: IO (Either Ex1 (Either Ex2 a))
+-- f = runEff $ \io -> do
+--   try $ \e1 -> do
+--     try $ \e2 -> do
+--       rethrowIO io e1 $ do
+--         rethrowIO io e2 $ doa
+--           Control.Exception.throw Ex1) (Control.Exception.throw E2)
+
+-- | Rethrow an exception raised by an 'IO' action as a Bluefin
+-- exception.
+--
+-- @
+-- 'runEff' $ \\io -> do
+--   r \<- 'try' $ \\ex -> do
+--     rethrowIO @'Control.Exception.IOException' io ex $ do
+--       effIO io ('Prelude.readFile' "\/tmp\/doesnt-exist")
+--
+--   'effIO' io $ putStrLn $ case r of
+--     Left e -> "Caught IOException:\\n" ++ show e
+--     Right contents -> contents
+-- @
+--
+-- @
+-- Caught ErrorCall:
+-- \/tmp\/doesnt-exist: openFile: does not exist (No such file or directory)
+-- @
+rethrowIO ::
+  forall ex es e1 e2 r.
+  (e1 :> es, e2 :> es, Control.Exception.Exception ex) =>
+  IOE e1 ->
+  Exception ex e2 ->
+  Eff es r ->
+  -- | ͘
+  Eff es r
+rethrowIO MkIOE ex body =
+  UnsafeMkEff
+    ( Control.Exception.catch
+        (unsafeUnEff body)
+        (\e -> unsafeUnEff (throw @_ @es ex e))
+    )
 
 -- | @bracket acquire release body@: @acquire@ a resource, perform the
 -- @body@ with it, and @release@ the resource even if @body@ threw an
diff --git a/src/Bluefin/Internal/Examples.hs b/src/Bluefin/Internal/Examples.hs
--- a/src/Bluefin/Internal/Examples.hs
+++ b/src/Bluefin/Internal/Examples.hs
@@ -77,6 +77,17 @@
   yield y 100
   pure length
 
+-- This shows we can use forEach at any level of nesting with
+-- insertManySecond
+doubleNestedForEach ::
+  (forall e. Stream () e -> Eff (e :& es) ()) ->
+  Eff es ()
+doubleNestedForEach f =
+  withState () $ \_ -> do
+    withState () $ \_ -> do
+      forEach (insertManySecond . f) (\_ -> pure ())
+      pure (\_ _ -> ())
+
 forEachExample :: ([Int], ())
 forEachExample = runPureEff $ yieldToList $ \y -> do
   forEach (inFoldable [0 .. 4]) $ \i -> do
@@ -877,3 +888,13 @@
           (\_ -> for_ [1 :: Int ..] $ \i -> yield y i)
     )
   effIO io (putStrLn "Finishing")
+
+rethrowIOExample :: IO ()
+rethrowIOExample = runEff $ \io -> do
+  r <- try $ \ex -> do
+    rethrowIO @Control.Exception.IOException io ex $ do
+      effIO io (Prelude.readFile "/tmp/doesnt-exist")
+
+  effIO io $ putStrLn $ case r of
+    Left e -> "Caught IOException:\n" ++ show e
+    Right contents -> contents
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -11,8 +11,8 @@
 import Prelude hiding (break, read)
 
 main :: IO ()
-main = do
-  runSpecH $ \y -> do
+main = runEff $ \io -> do
+  runSpecH io $ \y -> do
     let assertEqual' = assertEqual y
 
     assertEqual' "oddsUntilFirstGreaterThan5" oddsUntilFirstGreaterThan5 [1, 3, 5, 7]
@@ -53,26 +53,31 @@
           yield y2 ("But got: " ++ show c2)
     )
 
-type SpecInfo = Forall (Nest (Stream String) Eff)
+type SpecInfo r = Forall (Stream String :~> WrapEff r)
 
 withSpecInfo ::
   (forall e es. (e :> es) => Stream String e -> Eff es r) ->
   SpecInfo r
-withSpecInfo x = Forall (Nest x)
+withSpecInfo x = Forall (Nest (\s -> MkWrapEff (x s)))
 
-newtype Nest h t es r = Nest {unNest :: forall e. (e :> es) => h e -> t es r}
+newtype (h :~> t) es = Nest {unNest :: forall e. h e -> t (e :& es)}
 
-newtype Forall t r = Forall {unForall :: forall es. t es r}
+newtype Forall t = Forall {unForall :: forall es. t es}
 
+newtype WrapEff r es = MkWrapEff {unWrapEff :: Eff es r}
+
+instance Handle (WrapEff r) where
+  mapHandle (MkWrapEff e) = MkWrapEff (useImpl e)
+
 runTests ::
   forall es e3.
   (e3 :> es) =>
-  (forall e1 e2. SpecH e1 -> Eff (e1 :& e2 :& es) ()) ->
+  (forall e1. SpecH e1 -> Eff (e1 :& es) ()) ->
   Stream String e3 ->
   Eff es Bool
 runTests f y = do
   ((), All passedAll) <- runWriter $ \passedAllSoFar -> do
-    forEach f $ \(name, mFailure) -> do
+    forEach (useImplWithin f) $ \(name, mFailure) -> do
       let passed = case mFailure of
             Just _ -> False
             Nothing -> True
@@ -87,17 +92,19 @@
         Nothing -> pure ()
         Just n -> do
           yield y "" :: Eff (e2 :& es) ()
-          _ <- forEach (unNest (unForall n)) $ \entry -> do
+          _ <- forEach (unWrapEff . unNest (unForall n)) $ \entry -> do
             yield y ("    " ++ entry)
           yield y ""
 
   pure passedAll
 
 runSpecH ::
-  (forall e1 es. SpecH e1 -> Eff (e1 :& es) ()) ->
-  IO ()
-runSpecH f = runEff $ \ioe -> do
-  passed <- forEach (runTests f) $ \text ->
+  (e :> es) =>
+  IOE e ->
+  (forall e1. SpecH e1 -> Eff (e1 :& es) ()) ->
+  Eff es ()
+runSpecH ioe f = do
+  passed <- forEach (runTests (useImplWithin f)) $ \text ->
     effIO ioe (putStrLn text)
 
   effIO ioe $ case passed of
