tursodatabase/turso · error
query {} did not return a JSON plan
Error message
query {} did not return a JSON plan What it means
print_plan runs `EXPLAIN QUERY PLAN FORMAT=JSON <query>` and expects the first cell of the first row to be a Text value containing the JSON plan. If there are no rows, the row is empty, or the value is not Text (e.g. NULL or a blob), it fails with this error naming the query.
Source
Thrown at perf/join-benchmark/main.rs:182
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
- Run the query manually in tursodb: `EXPLAIN QUERY PLAN FORMAT=JSON <sql>;` to see what it returns.
- Fix the query SQL (missing/misspelled tables) so a plan is produced.
- Confirm the engine build supports EXPLAIN QUERY PLAN FORMAT=JSON; upgrade or drop the FORMAT clause.
- Check run_collect_rows results for errors swallowed upstream before the pattern match.
Example fix
// before
let sql = format!("EXPLAIN QUERY PLAN FORMAT=JSON {}", query.sql);
// after
// verify the statement first
connection.prepare(query.sql.clone())?.run_collect_rows()?;
let sql = format!("EXPLAIN QUERY PLAN FORMAT=JSON {}", query.sql); Defensive patterns
Strategy: try-catch
Try / catch
let rows = connection.prepare(sql)?.run_collect_rows()?;
let plan_text = rows.first().and_then(|r| r.first())
.and_then(|v| if let Value::Text(t) = v { Some(t.clone()) } else { None });
match plan_text {
Some(t) => println!("{}", t),
None => eprintln!("skipping plan for {} (no JSON plan returned)", query.name),
} Prevention
- Validate all query SQL references existing tables before benchmarking
- Confirm the engine build supports EXPLAIN QUERY PLAN FORMAT=JSON
- Spot-check one EXPLAIN QUERY PLAN output manually before batch runs
When it happens
Trigger: Calling print_plan for a query whose EXPLAIN QUERY PLAN FORMAT=JSON produced no output rows or a non-text first column — e.g. the query references a missing table so planning yields no plan, or the FORMAT=JSON option isn't supported so output shape differs.
Common situations: Query SQL referring to a table that doesn't exist in the benchmark database; older engine build without FORMAT=JSON support; prepare/run failing silently and returning an empty row set.
Related errors
- no SQL files matched the query selection
- query was interrupted
- database was busy
- InvalidData
- UnexpectedEof
AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-09-13).
Data as JSON: /api/errors/ba4e21246440b2bb.
Report an issue: GitHub.