tursodatabase/turso · error · anyhow::Error
latency worker panicked
Error message
latency worker panicked
What it means
`measure` spawns one worker thread per session; if any worker panics while executing queries, its JoinHandle yields an Err which `measure` converts to this error. It signals that a benchmark thread crashed mid-run rather than the query itself returning a normal error.
Solutions
- Fix the panic inside the `execute` closure (look for unwrap/expect/indexing).
- Check panic stderr output for the real panic message and location.
- Avoid panicking APIs in `execute`; return `Result::Err` instead so the error propagates normally.
Example fix
// before
let row = rows.get(i).unwrap();
// after
let Some(row) = rows.get(i) else { return Ok(RunResult::default()) }; Defensive patterns
Strategy: try-catch
Try / catch
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| execute(session, rt))) {
Ok(res) => res,
Err(_) => return Err(anyhow::anyhow!("worker panicked; check execute closure for unwrap/index panics")),
} Prevention
- Avoid unwrap/expect/panic in the execute closure; return Result instead
- Run the benchmark under a debugger or set RUST_BACKTRACE=1 to locate panics
- Test execute with a single connection/single query before scaling up
When it happens
Trigger: A worker thread passed to `measure` panics inside the user-supplied `execute` closure (e.g. index-out-of-bounds, unwrap on None, connection closed unexpectedly), making the scoped JoinHandle return an Err.
Common situations: A SQL executor bug or a panic in benchmark code running on a worker thread; a connection being closed or poisoned during the benchmark loop.
Related errors
- Could not determine home directory
- database was busy
- Error setting Ctrl-C handler
- failed to build IO runtime
- failed to generate random bytes
AI-assisted analysis of tursodatabase/turso@8d4a589f8d (2026-09-20).
Data as JSON: /api/errors/97479acf60b744fa.
Report an issue: GitHub.
Appendix: source
Thrown at perf/fts/src/latency.rs:68
result.rows += completed.rows;
result.id_sum += completed.id_sum;
}
Ok::<_, anyhow::Error>((result, latencies))
})
})
.collect();
let start = Instant::now();
barrier.wait();
let outcomes: Vec<_> = handles.into_iter().map(|handle| handle.join()).collect();
let seconds = start.elapsed().as_secs_f64();
let mut measurement = Measurement {
result: RunResult::default(),
seconds,
latencies: Vec::with_capacity(queries),
};
for outcome in outcomes {
let (result, latencies) =
outcome.map_err(|_| anyhow::anyhow!("latency worker panicked"))??;
measurement.result.queries += result.queries;
measurement.result.rows += result.rows;
measurement.result.id_sum += result.id_sum;
measurement.latencies.extend(latencies);
}
Ok(measurement)
})
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use std::sync::Mutex;
use super::*;
#[test]
fn uses_distinct_threads_and_records_each_query_with_uneven_work() -> Result<()> {View on GitHub (pinned to 8d4a589f8d)