tursodatabase/turso · error

Unexpected row for CREATE TABLE

Error message

Unexpected row for CREATE TABLE

What it means

During `tursodb import`, the importer executes the generated CREATE TABLE through conn.query plus run_with_row_callback. DDL must not yield rows, so any row callback invocation panics. Hitting it means the engine returned rows for a DDL statement (or the constructed statement was not actually DDL) - an internal invariant break, not a user configuration error.

Source

Thrown at cli/commands/import.rs:111

                let create_table = format!("CREATE TABLE {} ({});", args.table, columns);

                let rows = match self.conn.query(create_table) {
                    Ok(rows) => rows,
                    Err(e) => {
                        let _ = self
                            .writer
                            .write_all(format!("Error creating table: {e:?}\n").as_bytes());
                        return;
                    }
                };
                let Some(mut rows) = rows else {
                    let _ = self.writer.write_all(b"Error creating table\n");
                    return;
                };

                let res = rows.run_with_row_callback(|_| {
                    // Not expected for CREATE TABLE
                    panic!("Unexpected row for CREATE TABLE");
                });
                match res {
                    Ok(_) => {}
                    Err(LimboError::Busy | LimboError::Interrupt) => {
                        let _ = self
                            .writer
                            .write_all("Error creating table: interrupted / busy\n".as_bytes());
                        return;
                    }
                    Err(e) => {
                        let _ = self.writer.write_all(
                            format!("Error checking table existence: {e:?}\n").as_bytes(),
                        );
                        return;
                    }
                }
            } else {
                let _ = self.writer.write_all(b"Error: Empty input file\n");

View on GitHub (pinned to c1e5928725)

Solutions

  1. Upgrade to a build where the regression is fixed; if it reproduces on latest, file an issue with the CSV header and exact command
  2. Pre-create the table yourself and import into it, skipping the CREATE TABLE path
  3. Normalize or quote CSV header identifiers before importing

Example fix

# before
tursodb import data.csv --table users   # panics: Unexpected row for CREATE TABLE

# after
# pre-create the schema so the importer does not run DDL
sqlite3 new.db 'CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT);'
tursodb import data.csv --table users
Defensive patterns

Strategy: fallback

Validate before calling

# smoke-test that DDL on this build yields no rows before importing real data
printf 'CREATE TABLE _probe(x);\n' | tursodb >/dev/null && echo ddl-ok

Try / catch

import subprocess
rc = subprocess.run(['tursodb','import','data.csv','--table','users']).returncode
if rc != 0:
    # fall back: create schema via sqlite3, or import there entirely
    ...

Prevention

When it happens

Trigger: Running `tursodb import file.csv --table name` on a build where statement execution returns rows for CREATE TABLE; CSV-header identifiers that make the generated CREATE TABLE degenerate into something row-returning; planner/executor regressions in statement classification.

Common situations: Nightly or regression builds of the CLI; exotic column names from CSV headers; testing import right after engine changes to statement handling.

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


AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-20). Data as JSON: /api/errors/f8662c686c8aad22. Report an issue: GitHub.