diff --git a/src/dht.cpp b/src/dht.cpp
index 08af886c065b9ca0334f52c7a675ff559a931ce9..843e6343e516c71cfbcc9d1513f3365369671bf4 100644
--- a/src/dht.cpp
+++ b/src/dht.cpp
@@ -582,10 +582,11 @@ Dht::Search::insertNode(std::shared_ptr<Node> node, time_point now, const Blob&
     const auto& nid = node->id;
 
     // Fast track for the case where the node is not relevant for this search
-    if (nodes.size() >= SEARCH_NODES && id.xorCmp(nid, nodes.back().node->id) > 0)
+    if (node->isExpired() && nodes.size() >= SEARCH_NODES && id.xorCmp(nid, nodes.back().node->id) > 0)
         return false;
 
     bool found = false;
+    unsigned num_bad_nodes = getNumberOfBadNodes();
     auto n = std::find_if(nodes.begin(), nodes.end(), [&](const SearchNode& sn) {
         if (sn.node == node) {
             found = true;
@@ -596,13 +597,15 @@ Dht::Search::insertNode(std::shared_ptr<Node> node, time_point now, const Blob&
 
     bool new_search_node = false;
     if (!found) {
-        // Be more restricitve if there are
-        // too many nodes in this search,
-        if (nodes.size() >= SEARCH_NODES && n == nodes.end())
-            return false;
+        // Be more restricitve if there are too many
+        // good or unknown nodes in this search,
+        if (nodes.size() - num_bad_nodes >= SEARCH_NODES) {
+            if (node->isExpired() or n == nodes.end())
+                return false;
+        }
 
         // Reset search timer if the search is empty
-        else if (nodes.empty()) {
+        if (nodes.empty()) {
             step_time = TIME_INVALID;
         }
 
@@ -610,13 +613,17 @@ Dht::Search::insertNode(std::shared_ptr<Node> node, time_point now, const Blob&
         node->time = now;
         new_search_node = true;
 
-        // trim nodes
-        while (nodes.size() > SEARCH_NODES) {
-            auto to_remove = std::prev(nodes.end());
-            if (to_remove->getStatus and to_remove->getStatus->pending()) {
-                to_remove->getStatus->cancel();
-            }
-            nodes.erase(to_remove);
+        // trim good nodes
+        while (nodes.size() - num_bad_nodes > SEARCH_NODES) {
+            if (removeExpiredNode(now))
+                num_bad_nodes--;
+
+            auto to_remove = std::find_if(nodes.rbegin(), nodes.rend(),
+                [&](const SearchNode& n) { return not n.isBad(); }
+            );
+            if (to_remove != nodes.rend()) {
+                nodes.erase(std::prev(to_remove.base()));
+            } // else, all nodes are expired.
         }
         expired = false;
     }
@@ -2444,7 +2451,7 @@ Dht::onError(std::shared_ptr<Request> req, DhtProtocolException e) {
             auto& sr = srp.second;
             for (auto& n : sr->nodes) {
                 if (n.node != req->node) continue;
-                network_engine.cancelRequest(n.getStatus);
+                n.token.clear();
                 n.last_get_reply = time_point::min();
                 cleared++;
                 searchSendGetValues(sr);