{"record":{"id":"eec42a237e8a5d73","repo":"tursodatabase/turso","slug":"unexpected-row-for-insert","errorCode":null,"errorMessage":"Unexpected row for INSERT","messagePattern":"Unexpected row for INSERT","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/commands/import.rs","lineNumber":165,"sourceCode":"            };\n\n            if !record.is_empty() {\n                let values: Vec<String> = record\n                    .iter()\n                    .map(|r| format!(\"'{}'\", r.replace(\"'\", \"''\")))\n                    .collect();\n                batch.push(values.join(\",\"));\n\n                if batch.len() >= CSV_INSERT_BATCH_SIZE {\n                    println!(\"Inserting batch of {} rows\", batch.len());\n                    let insert_string =\n                        format!(\"INSERT INTO {} VALUES ({});\", args.table, batch.join(\"),(\"));\n\n                    match self.conn.query(insert_string) {\n                        Ok(rows) => {\n                            if let Some(mut rows) = rows {\n                                let res = rows.run_with_row_callback(|_| {\n                                    panic!(\"Unexpected row for INSERT\");\n                                });\n                                match res {\n                                    Ok(_) => {\n                                        success_rows += batch.len() as u64;\n                                    }\n                                    Err(LimboError::Interrupt) => {\n                                        let _ = self.writer.write_all(b\"interrupt\\n\");\n\n                                        failed_rows += batch.len() as u64;\n                                    }\n                                    Err(LimboError::Busy) => {\n                                        let _ = self.writer.write_all(b\"database is busy\\n\");\n\n                                        failed_rows += batch.len() as u64;\n                                    }\n                                    Err(e) => {\n                                        let _ = self.writer.write_all(\n                                            format!(\"Error executing query: {e:?}\\n\").as_bytes(),","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/cli/commands/import.rs#L147-L183","documentation":"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.","triggerScenarios":"`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).","commonSituations":"Bulk-loading realistic CSVs on a regression build; CI import tests after executor changes.","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"],"exampleFix":"# before\ntursodb import big.csv --table t   # panics: Unexpected row for INSERT\n\n# after\nsqlite3 t.db \".mode csv\" \".import big.csv t\"\n# then continue using t.db from tursodb","handlingStrategy":"fallback","validationCode":"import subprocess\nrc = subprocess.run(['tursodb','import','sample.csv','--table','t']).returncode\nif rc != 0:\n    raise SystemExit('import path broken; fall back to sqlite3 .import')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["cli","import","csv","insert","batch","invariant","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}