tursodatabase/turso · error
query was interrupted
Error message
query was interrupted
What it means
The benchmark's execute loop steps a prepared statement to completion. A StepResult::Interrupt means the database was interrupted (interrupt flag set) while the query was running, so the benchmark bails out instead of returning partial row counts.
Source
Thrown at perf/join-benchmark/main.rs:172
.with_context(|| format!("read query file {}", path.display()))?,
});
}
Ok(queries)
}
fn set_timeout(statement: &mut turso_core::Statement, timeout_seconds: u64) {
let timeout = (timeout_seconds != 0).then(|| Duration::from_secs(timeout_seconds));
statement.set_query_timeout_override(Some(timeout));
}
fn execute(database: &Database, statement: &mut turso_core::Statement) -> Result<u64> {
let mut result_rows = 0_u64;
loop {
match statement.step()? {
StepResult::Row => result_rows = result_rows.saturating_add(1),
StepResult::IO | StepResult::Yield | StepResult::Sleep { .. } => database.io.step()?,
StepResult::Done => return Ok(result_rows),
StepResult::Interrupt => bail!("query was interrupted"),
StepResult::Busy => bail!("database was busy"),
}
}
}
fn print_plan(connection: &Arc<turso_core::Connection>, query: &Query) -> Result<()> {
let sql = format!("EXPLAIN QUERY PLAN FORMAT=JSON {}", query.sql);
let rows = connection.prepare(sql)?.run_collect_rows()?;
let Some(Value::Text(plan)) = rows.first().and_then(|row| row.first()) else {
bail!("query {} did not return a JSON plan", query.name);
};
let plan: JsonValue = serde_json::from_str(plan.as_str())?;
println!("{}", json!({"query": query.name, "plan": plan}));
Ok(())
}
View on GitHub (pinned to 492c4a71cd)
Solutions
- Increase the benchmark time budget/timeout so the query finishes before the interrupt fires.
- Optimize or disable the offending query (check indexes/join order) to make it complete within the limit.
- Check what sets the interrupt flag (signal handler, deadline task) and whether it fires prematurely.
- Retry the run; if it's consistently interrupted, profile the query for a pathological plan.
Example fix
// before let deadline = Instant::now() + Duration::from_secs(5); // after let deadline = Instant::now() + Duration::from_secs(60);
Defensive patterns
Strategy: try-catch
Try / catch
match execute(&database, &mut statement) {
Err(e) if e.to_string().contains("query was interrupted") => {
eprintln!("query exceeded time budget: {e}");
// raise budget or skip query
}
other => other?,
} Prevention
- Set per-query time budgets larger than the slowest expected query
- Check what wires interrupts (deadline timers, signal handlers) and test thresholds
- Profile queries that are repeatedly interrupted for pathological plans
When it happens
Trigger: statement.step() returns StepResult::Interrupt during a long join query — the database/connection interrupt flag was set, e.g. by a deadline/timeout mechanism or an external interrupt request.
Common situations: Query exceeding an imposed time limit with interrupt wired to a timer; Ctrl-C handling that flags the database; long-running join hitting a harness timeout.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- no SQL files matched the query selection
- database was busy
- query {} did not return a JSON plan
- InvalidData
- UnexpectedEof
AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-09-13).
Data as JSON: /api/errors/745ebdc5f8615fdb.
Report an issue: GitHub.