diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## Zip 2.2.2
+
+* Make `sourceEntry` close file handles promptly. [Issue
+  142](https://github.com/mrkkrp/zip/issues/142).
+
 ## Zip 2.2.1
 
 * Don't add Zip64 fields when copying entries from another archive
diff --git a/Codec/Archive/Zip/Internal.hs b/Codec/Archive/Zip/Internal.hs
--- a/Codec/Archive/Zip/Internal.hs
+++ b/Codec/Archive/Zip/Internal.hs
@@ -238,18 +238,29 @@
   Bool ->
   -- | Source of uncompressed data
   ConduitT () ByteString m ()
-sourceEntry path EntryDescription {..} d =
-  source .| CB.isolate (fromIntegral edCompressedSize) .| decompress
+sourceEntry path (EntryDescription {..}) d =
+  -- We cannot simply use CB.sourceIOHandle
+  -- because that closes the archive only when its end is reached.
+  -- See <https://github.com/mrkkrp/zip/issues/142>.
+  -- The following implementation closes file handles promptly.
+  C.bracketP
+    ( do
+        h <- openBinaryFile path ReadMode
+        hSeek h AbsoluteSeek (fromIntegral edOffset)
+        localHeader <- B.hGet h 30
+        case runGet getLocalHeaderGap localHeader of
+          Left msg -> throwM (ParsingFailed path msg)
+          Right gap -> do
+            hSeek h RelativeSeek gap
+            return h
+    )
+    hClose
+    ( \h ->
+        CB.sourceHandle h
+          .| CB.isolate (fromIntegral edCompressedSize)
+          .| decompress
+    )
   where
-    source = CB.sourceIOHandle $ do
-      h <- openFile path ReadMode
-      hSeek h AbsoluteSeek (fromIntegral edOffset)
-      localHeader <- B.hGet h 30
-      case runGet getLocalHeaderGap localHeader of
-        Left msg -> throwM (ParsingFailed path msg)
-        Right gap -> do
-          hSeek h RelativeSeek gap
-          return h
     decompress =
       if d
         then decompressingPipe edCompression
diff --git a/zip.cabal b/zip.cabal
--- a/zip.cabal
+++ b/zip.cabal
@@ -1,11 +1,11 @@
 cabal-version:   2.4
 name:            zip
-version:         2.2.1
+version:         2.2.2
 license:         BSD-3-Clause
 license-file:    LICENSE.md
 maintainer:      Mark Karpov <markkarpov92@gmail.com>
 author:          Mark Karpov <markkarpov92@gmail.com>
-tested-with:     ghc ==9.8.4 ghc ==9.10.1 ghc ==9.12.1
+tested-with:     ghc ==9.10.3 ghc ==9.12.4 ghc ==9.14.1
 homepage:        https://github.com/mrkkrp/zip
 bug-reports:     https://github.com/mrkkrp/zip/issues
 synopsis:        Operations on zip archives
@@ -55,7 +55,7 @@
         cereal >=0.3 && <0.6,
         conduit >=1.3 && <1.4,
         conduit-extra >=1.3 && <1.4,
-        containers >=0.5 && <0.8,
+        containers >=0.5 && <0.9,
         digest <0.1,
         directory >=1.2.2 && <1.4,
         dlist >=0.8 && <2.0,
@@ -65,7 +65,7 @@
         mtl >=2 && <3,
         resourcet >=1.2 && <1.4,
         text >=0.2 && <2.2,
-        time >=1.4 && <1.15,
+        time >=1.4 && <1.16,
         transformers >=0.4 && <0.7,
         transformers-base
 
@@ -124,14 +124,14 @@
         QuickCheck >=2.4 && <3,
         bytestring >=0.9 && <0.13,
         conduit >=1.3 && <1.4,
-        containers >=0.5 && <0.8,
+        containers >=0.5 && <0.9,
         directory >=1.2.2 && <1.4,
         dlist >=0.8 && <2,
         filepath >=1.2 && <1.6,
         hspec >=2 && <3,
         temporary >=1.1 && <1.4,
         text >=0.2 && <2.2,
-        time >=1.4 && <1.15,
+        time >=1.4 && <1.16,
         zip
 
     if flag(dev)
