tursodatabase/turso · error
Unexpected row for INSERT
Error message
Unexpected row for INSERT
What it means
Batched CSV import builds one multi-row INSERT (CSV_INSERT_BATCH_SIZE rows per statement) and runs it via conn.query with run_with_row_callback. INSERT must not produce rows, so a row callback firing means the executor returned rows for DML - an engine-side invariant break and the CLI panics to surface it.
Source
Thrown at cli/commands/import.rs:165
};
if !record.is_empty() {
let values: Vec<String> = record
.iter()
.map(|r| format!("'{}'", r.replace("'", "''")))
.collect();
batch.push(values.join(","));
if batch.len() >= CSV_INSERT_BATCH_SIZE {
println!("Inserting batch of {} rows", batch.len());
let insert_string =
format!("INSERT INTO {} VALUES ({});", args.table, batch.join("),("));
match self.conn.query(insert_string) {
Ok(rows) => {
if let Some(mut rows) = rows {
let res = rows.run_with_row_callback(|_| {
panic!("Unexpected row for INSERT");
});
match res {
Ok(_) => {
success_rows += batch.len() as u64;
}
Err(LimboError::Interrupt) => {
let _ = self.writer.write_all(b"interrupt\n");
failed_rows += batch.len() as u64;
}
Err(LimboError::Busy) => {
let _ = self.writer.write_all(b"database is busy\n");
failed_rows += batch.len() as u64;
}
Err(e) => {
let _ = self.writer.write_all(
format!("Error executing query: {e:?}\n").as_bytes(),View on GitHub (pinned to 244cde92a7)
Solutions
- Update the CLI/engine to a fixed build; report with the failing CSV and generated batch statement if current
- Fall back to importing with the sqlite3 CLI (same file format), then reopen the database with tursodb
- Import a small sample first to detect a broken import path before loading large files
Example fix
# before tursodb import big.csv --table t # panics: Unexpected row for INSERT # after sqlite3 t.db ".mode csv" ".import big.csv t" # then continue using t.db from tursodb
Defensive patterns
Strategy: fallback
Validate before calling
import subprocess
rc = subprocess.run(['tursodb','import','sample.csv','--table','t']).returncode
if rc != 0:
raise SystemExit('import path broken; fall back to sqlite3 .import') Prevention
- Validate the bulk-import pipeline with a small sample file first
- Keep a sqlite3-CLI import script as a documented fallback for bulk loads
- Pin a known-good engine/CLI version for production imports
When it happens
Trigger: `tursodb import` over a CSV large enough to fill a batch, on a build where INSERT execution signals rows; also if the constructed multi-row statement string degenerates into something row-returning (e.g. RETURNING-handling regressions).
Common situations: Bulk-loading realistic CSVs on a regression build; CI import tests after executor changes.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Unexpected row for CREATE TABLE
- Could not determine home directory
- Error setting Ctrl-C handler
- 1
- register holds unexpected value: {self:?}
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/eec42a237e8a5d73.
Report an issue: GitHub.