tursodatabase/turso · error
row count mismatch for
Error message
row count mismatch for {case:?} What it means
For all non-ranked query cases (And, Or, Phrase), validate_result asserts the returned row count equals the full expected match count times the number of queries executed. ensure! at perf/fts/src/main.rs:338 fails when the engine returned a different number of rows than the seeded-data predicate predicts for that case.
Solutions
- Verify the FTS index is fully built/populated before running validation queries
- Run with --queries 1 to see whether a single query already returns the wrong count
- Compare against sqlite3 FTS5 output for the same corpus (differential check)
- Align the predicate in validate_result with the actual query being executed
Example fix
// before
ensure!(rows == expected_rows, "row count mismatch");
// after
ensure!(rows == expected_rows * queries, "row count mismatch for {case:?}"); Defensive patterns
Strategy: try-catch
Validate before calling
let expected: usize = (0..n).filter(|&id| predicate(id)).count() * queries;
Try / catch
if let Err(e) = validate_result(...) {
if e.to_string().starts_with("row count mismatch") {
eprintln!("got {rows} rows, expected {expected}; check FTS index population");
}
return Err(e);
} Prevention
- Fully populate and commit the FTS index before benchmarking
- Keep the row-count model in validate_result aligned with the actual query text
- Diff results against sqlite3 FTS5 for the same corpus when counts drift
- Run MVCC/WAL modes with quiesced writers during validation
When it happens
Trigger: validate_result invoked with case And/Or/Phrase where rows != expected_rows * queries — the engine under- or over-returned rows for the repeated query, e.g. wrong tokenization, missing index entries, or visibility differences.
Common situations: FTS index not fully populated before querying; predicate in validate_result out of sync with the actual query text; MVCC/WAL snapshot hiding committed rows; a regression in the FTS match implementation.
Related errors
- ranked row count mismatch
- connections must be positive
- documents must be positive
- ID sum mismatch for
- index contains segment bytes, below requested minimum …
AI-assisted analysis of tursodatabase/turso@8d4a589f8d (2026-09-20).
Data as JSON: /api/errors/64745f06e236b324.
Report an issue: GitHub.
Appendix: source
Thrown at perf/fts/src/main.rs:338
queries: usize,
rows: usize,
sum: i64,
) -> Result<()> {
let ids = (0..documents).filter(|id| match case {
QueryCase::Rare => id % 100 == 0,
QueryCase::Common => true,
QueryCase::And => id % 6 == 0,
QueryCase::Or | QueryCase::Ranked => id % 2 == 0 || id % 3 == 0,
QueryCase::Phrase => id % 200 == 0,
});
let expected_rows = ids.clone().count();
if matches!(case, QueryCase::Ranked) {
ensure!(
rows == expected_rows.min(10) * queries,
"ranked row count mismatch"
);
} else {
ensure!(
rows == expected_rows * queries,
"row count mismatch for {case:?}"
);
ensure!(
sum == ids.map(|id| id as i64).sum::<i64>() * queries as i64,
"ID sum mismatch for {case:?}"
);
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn rejects_mixing_search_latency_and_throughput_options() -> Result<()> {
for options in [View on GitHub (pinned to 8d4a589f8d)