Repository navigation
Description
Summary
Turso/libsql GET /dump output cannot always be replayed by a stock SQLite parser. When a database contains a virtual table whose CREATE statement itself contains single quotes — the common case is an FTS5 external-content table, e.g. content='chunks' — the dump registers the virtual table inside a PRAGMA writable_schema=ON; ... OFF; block with a statement like:
INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql) VALUES('table','chunks_fts','chunks_fts',0,'CREATE VIRTUAL TABLE chunks_fts
USING fts5(text, content='chunks', content_rowid='id')');The embedded SQL text is emitted verbatim: its single quotes are not doubled (''), so the string literal terminates early and every stock SQLite parser fails with near "chunks": syntax error.
This is an upstream libsql dump-generation bug (the same class of bug stock sqlite3 .dump avoids by escaping). It is filed here only to document the quirk and the workaround; nothing is filed upstream.
Impact
Found live 2026-10-27 on the atlas database: pkgs/cold-store-reaper/scripts/export-turso.sh downloads /dump and rebuilds it with sqlite3 -bail, which hard-fails on this statement — so any Turso database with a quoted virtual-table definition (FTS5 content= tables in practice) can never be filed into the cold store.
Workaround (this repo)
export-turso.sh runs the downloaded dump through a streaming repair filter before the rebuild. The filter passes every line through byte-identical except INSERT INTO sqlite_schema(...) statements inside a writable_schema block whose final SQL literal is verifiably mis-escaped (a lone, undoubled single quote in the literal body): for those it rewrites the literal with proper '' doubling so the statement parses and registers the virtual table exactly as authored. Correctly-escaped statements and all other lines pass through unchanged.
Notes
- Detection is parse-based and conservative: a statement is only rewritten when its final literal cannot be a valid SQL string literal as emitted.
- The truncation guard (dump must end in
COMMIT;) applies to the filtered stream.
Acceptance criteria
-
pkgs/cold-store-reaper/scripts/export-turso.sh(or a helper it calls) contains the streaming repair filter the body describes: onlyINSERT INTO sqlite_schema(...)statements inside awritable_schemablock whose final SQL literal is verifiably mis-escaped are rewritten, with''doubling; every other line passes byte-identical - A fixture dump containing an FTS5 external-content virtual table (quoted
content=definition) rebuilds cleanly through the export path withsqlite3 -bail - Correctly-escaped dumps are unchanged by the filter (byte-identical output), and the
COMMIT;truncation guard still applies to the filtered stream - A test/fixture covers both the mis-escaped and correctly-escaped cases so the workaround cannot silently rot
Activity
developing-today commentedon Oct 27, 2026
CODE-483
dezren39 commentedon Oct 27, 2026
Intake review — fleet monitor (2026-10-27)
Still live — and the body overstates the current state. The issue says the workaround already runs in
export-turso.sh, but a code search of current main forwritable_schema/sqlite_schemareturns no hits anywhere in the repo (checked 2026-10-27, local clone + GitHub code search): the repair filter is described, not landed. So the remaining work is implementation + fixture test, not just documentation.Related: the cold-store turso hardening line of work (PR #1383, GB-class export hardening, merged today) touches the same script — coordinate so the filter lands on top of it, not against it.
Risks: a non-conservative filter could corrupt valid dumps; the parse-based, lone-quote-only detection in the body is the right constraint — keep it.
Suggested approach: implement the filter as a small separately-testable script invoked by
export-turso.sh, with the two fixtures above.cold-store: streaming repair filter for libsql /dump's unescaped sqli…
Merge pull request #1398 from developing-today/cold-store-turso-dump-…