From 0c5e9eb104eb0a84667d060f54031de3a838802b Mon Sep 17 00:00:00 2001 From: Charlie Tonneslan Date: Mon, 18 May 2026 10:08:37 -0400 Subject: [PATCH] Skip type detection when CSV insert created no table Closes #702. A CSV that's only a header row leaves insert_all with no rows, so no table gets created. The follow-up transform(types=tracker.types) hit the 'Cannot transform a table that doesn't exist yet' assertion. Guard both insert paths on the table actually existing. Signed-off-by: Charlie Tonneslan --- sqlite_utils/cli.py | 6 ++++-- tests/test_cli.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index 5844dfc0..69374cd6 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -1175,7 +1175,9 @@ def insert_upsert_implementation( ) else: raise - if tracker is not None: + if tracker is not None and db.table(table).exists(): + # A header-only CSV creates no table, so there is nothing to + # retype - skip the transform to avoid the assertion in it. db.table(table).transform(types=tracker.types) # Clean up open file-like objects @@ -2032,7 +2034,7 @@ def memory( rows = (_flatten(row) for row in rows) db.table(file_table).insert_all(rows, alter=True) - if tracker is not None: + if tracker is not None and db.table(file_table).exists(): db.table(file_table).transform(types=tracker.types) # Add convenient t / t1 / t2 views view_names = ["t{}".format(i + 1)] diff --git a/tests/test_cli.py b/tests/test_cli.py index 40b36854..9547e1ec 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2296,6 +2296,21 @@ def test_insert_detect_types(tmpdir, option): ] +def test_insert_detect_types_header_only_csv(tmpdir): + """A CSV that is only a header row creates no table; --detect-types should + not crash trying to transform it. Regression for #702.""" + db_path = str(tmpdir / "test.db") + result = CliRunner().invoke( + cli.cli, + ["insert", db_path, "creatures", "-", "--csv", "--detect-types"], + catch_exceptions=False, + input="name,age,weight\n", + ) + assert result.exit_code == 0 + db = Database(db_path) + assert "creatures" not in db.table_names() + + @pytest.mark.parametrize("option", (None, "-d", "--detect-types")) def test_upsert_detect_types(tmpdir, option): """Test that type detection is now the default behavior for upsert"""