test_snapshot_in_a_divergent_chain loads a UTXO snapshot while the background chainstate is on a stale lower-work branch below the snapshot base, then completes background validation without a restart.
Add this before connecting node 3 to node 0:
@@ -256,6 +256,8 @@ class AssumeutxoTest(BitcoinTestFramework):
assert_equal(normal['target'], target_str(REGTEST_TARGET))
assert_equal(normal['target'], snapshot['target'])
+ self.restart_node(3)
+
# Now lets sync the nodes and wait for the background validation to finish
self.connect_nodes(0, 3)
self.sync_blocks(nodes=(n0, n3))
The restart aborts in ReachedTarget() because startup assumes the background chainstate is already on the snapshot’s branch.
A later restart with the same datadir aborts in the same way: restarting in this state should not abort.
Assertion failed: (!target_block || target_block->GetAncestor(m_chain.Height()) == m_chain.Tip()), function ReachedTarget, file validation.h, line 680.
This is a low-priority edge case that requires loading the snapshot while the node remains on the stale branch, then restarting before background validation catches up - unlikely, but the assertion over-promises regardless. I am documenting it as an example of the inconsistencies created by the secondary chainstate. Rather than adjusting each one separately, I think we should remove it as proposed in #32377.