diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 8a34f0c9b..aa0087118 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -479,26 +479,6 @@ struct LocalStore::GCState
 };
 
 
-void LocalStore::deleteFromStore(GCState & state, std::string_view baseName)
-{
-    Path path = storeDir + "/" + std::string(baseName);
-    Path realPath = realStoreDir + "/" + std::string(baseName);
-
-    printInfo("deleting '%1%'", path);
-
-    state.results.paths.insert(path);
-
-    uint64_t bytesFreed;
-    deletePath(realPath, bytesFreed);
-    state.results.bytesFreed += bytesFreed;
-
-    if (state.results.bytesFreed > state.options.maxFreed) {
-        printInfo("deleted more than %d bytes; stopping", state.options.maxFreed);
-        throw GCLimitReached();
-    }
-}
-
-
 /* Unlink all files in /nix/store/.links that have a link count of 1,
    which indicates that there are no other links and so they can be
    safely deleted.  FIXME: race condition with optimisePath(): we
@@ -677,10 +657,31 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
         state.roots.insert(root.first);
     }
 
+    /* Helper function that deletes a path from the store and throws
+       GCLimitReached if we've deleted enough garbage. */
+    auto deleteFromStore = [&](std::string_view baseName)
+    {
+        Path path = storeDir + "/" + std::string(baseName);
+        Path realPath = realStoreDir + "/" + std::string(baseName);
+
+        printInfo("deleting '%1%'", path);
+
+        state.results.paths.insert(path);
+
+        uint64_t bytesFreed;
+        deletePath(realPath, bytesFreed);
+        state.results.bytesFreed += bytesFreed;
+
+        if (state.results.bytesFreed > state.options.maxFreed) {
+            printInfo("deleted more than %d bytes; stopping", state.options.maxFreed);
+            throw GCLimitReached();
+        }
+    };
+
     /* Helper function that visits all paths reachable from `start`
        via the referrers edges and optionally derivers and derivation
-       output edges. If any of those paths is a root, then we cannot
-       delete this path. */
+       output edges. If none of those paths are roots, then all
+       visited paths are garbage and are deleted. */
     auto deleteReferrersClosure = [&](const StorePath & start) {
         StorePathSet visited;
         std::queue<StorePath> todo;
@@ -769,7 +770,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
             if (!state.dead.insert(path).second) continue;
             if (state.shouldDelete) {
                 invalidatePathChecked(path);
-                deleteFromStore(state, path.to_string());
+                deleteFromStore(path.to_string());
             }
         }
     };
@@ -813,7 +814,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
                 if (auto storePath = maybeParseStorePath(storeDir + "/" + name))
                     deleteReferrersClosure(*storePath);
                 else
-                    deleteFromStore(state, name);
+                    deleteFromStore(name);
 
             }
         } catch (GCLimitReached & e) {
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 21a4e60cf..15475f402 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -240,8 +240,6 @@ private:
 
     struct GCState;
 
-    void deleteFromStore(GCState & state, std::string_view baseName);
-
     void findRoots(const Path & path, unsigned char type, Roots & roots);
 
     void findRootsNoTemp(Roots & roots, bool censor);