Flaky test: VectorIndex_Search_Prunes_Node_Visits can return zero matches because HNSW levels use an unseeded Random
LiteDB.Tests.QueryTest.VectorIndex_Tests.VectorIndex_Search_Prunes_Node_Visits failed on dev at 31f9a7f4 in the Test (Windows net481) job with:
Expected stats.Matches to contain only items matching (id <= 64), but the collection is empty.
at LiteDB.Tests.Query.VectorIndex_Tests.cs(591)The identical tree passed the same net481 job 20 minutes earlier on PR #2755 (run 35152785054), and net462 passed in the failing run. The test data is fully deterministic (two clusters of 64 fixed vectors), so the variation is inside the index.
Cause
LiteDB/Engine/Services/VectorIndexService.cs:16:
private readonly Random _random = new Random();SampleLevel() uses it to pick the HNSW level of every inserted node, so the graph topology differs on every process start. The test searches with maxDistance: 0.25, limit: 5, and Search tightens pruneDistance to the current worst result as it goes. With an unlucky level assignment the greedy descent can enter the far cluster and prune every near-cluster node before visiting it, returning no matches. This is a property of approximate search with pruning; the test asserts an exact outcome.
Options
- Make the level sampler deterministic for tests, for example an internal seed hook or a
Randominjected throughVectorIndexOptions(a fixed seed also makes index builds reproducible, which helps debugging). - Keep the pruning assertion (
Total > Visited) but relax the match assertion to tolerate an empty result, or search with a largermaxDistance/limitso pruning cannot exclude the whole cluster. - Seed
_randomfrom something stable per index (for example the collection name hash) so the same insert sequence always yields the same graph.
Option 1 fixes the flake without changing production behaviour. Surfaced by the new .NET Framework test job from #2903, which is simply one more process in which the dice are rolled; nothing suggests it is Framework-specific.
Source: litedb-org/LiteDB