diff --git a/src/validation.cpp b/src/validation.cpp
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3079,21 +3079,32 @@
         // nStatus" criteria for inclusion in setBlockIndexCandidates).
 
         invalid_walk_tip->nStatus =
-            invalidate ? invalid_walk_tip->nStatus.withFailedParent()
-                       : invalid_walk_tip->nStatus.withParkedParent();
+            invalidate ? invalid_walk_tip->nStatus.withFailed()
+                       : invalid_walk_tip->nStatus.withParked();
 
         setDirtyBlockIndex.insert(invalid_walk_tip);
         setBlockIndexCandidates.insert(invalid_walk_tip->pprev);
 
-        // If we abort invalidation after this iteration, make sure
-        // the last disconnected block gets marked failed (rather than
-        // just child of failed)
+        if (invalid_walk_tip->pprev == to_mark_failed_or_parked &&
+            (invalidate ? to_mark_failed_or_parked->nStatus.hasFailed()
+                        : to_mark_failed_or_parked->nStatus.isParked())) {
+            // We only want to mark the last disconnected block as
+            // BLOCK_FAILED_VALID; its children need to be BLOCK_FAILED_CHILD
+            // instead.
+            to_mark_failed_or_parked->nStatus =
+                to_mark_failed_or_parked->nStatus.withClearedFailureFlags()
+                    .withFailedParent()
+                    .withParkedParent();
+            setDirtyBlockIndex.insert(to_mark_failed_or_parked);
+        }
+
+        // Track the last disconnected block, so we can correct its
+        // BLOCK_FAILED_CHILD status in future iterations, or, if it's the last
+        // one, call InvalidChainFound on it.
         to_mark_failed_or_parked = invalid_walk_tip;
     }
 
     {
-        // Mark pindex (or the last disconnected block) as invalid or parked,
-        // regardless of whether it was in the main chain or not.
         LOCK(cs_main);
         if (chainActive.Contains(to_mark_failed_or_parked)) {
             // If the to-be-marked invalid block is in the active chain,
@@ -3101,6 +3112,8 @@
             return false;
         }
 
+        // Mark pindex (or the last disconnected block) as invalid (or parked),
+        // even when it never was in the main chain.
         to_mark_failed_or_parked->nStatus =
             invalidate ? to_mark_failed_or_parked->nStatus.withFailed()
                        : to_mark_failed_or_parked->nStatus.withParked();