tursodatabase/turso · error

ID sum mismatch for

Error message

ID sum mismatch for {case:?}

What it means

After the row count check, validate_result sums the returned ID column and compares it against the sum of expected matching IDs times the query count. ensure! at perf/fts/src/main.rs:342 fails when the row count matches but the returned IDs differ — the engine returned the right number of rows containing wrong values (duplicates, wrong ids, corruption).

Solutions

  1. Collect and sort the returned ids and diff them against ids.filter(predicate) to see which ids differ
  2. Check for duplicate ids in the result set (count matches but sum wrong often implies substitution)
  3. Rebuild the FTS index from scratch and re-validate to rule out index corruption
  4. Verify id type/projection in the query matches the i64 sum expectation

Example fix

// before
ensure!(sum == expected_sum * queries as i64, "sum mismatch");
// after
let mut got: Vec<i64> = collected_ids; got.sort();
let mut want: Vec<i64> = expected_ids; want.sort();
assert_eq!(got, want, "ID set mismatch for {case:?}");
Defensive patterns

Strategy: try-catch

Validate before calling

let expected_sum: i64 = (0..n).filter(|&id| predicate(id)).map(|id| id as i64).sum::<i64>() * queries as i64;

Try / catch

if let Err(e) = validate_result(...) {
    if e.to_string().starts_with("ID sum mismatch") {
        eprintln!("sum {sum} != expected {expected_sum}; compare sorted id sets");
    }
    return Err(e);
}

Prevention

When it happens

Trigger: validate_result with case And/Or/Phrase where sum != sum(expected ids) * queries — correct row count but wrong id values, e.g. rows substituted, ids computed differently, or duplicated/missing ids that coincidentally balance the count.

Common situations: Integer/id encoding bugs in the FTS result projection; ordering-independent comparison missing duplicate ids; storage corruption under WAL/MVCC; docid assignment drift after incremental inserts/deletes.

Related errors


AI-assisted analysis of tursodatabase/turso@8d4a589f8d (2026-09-20). Data as JSON: /api/errors/bdd258da6d38c03b. Report an issue: GitHub.

Appendix: source

Thrown at perf/fts/src/main.rs:342

    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 [
            vec![
                "--benchmark",
                "search",
                "--connections",

View on GitHub (pinned to 8d4a589f8d)