tursodatabase/turso · error · TypeError

sqlite3.Row is not supported as a row_factory on turso conne

Error message

sqlite3.Row is not supported as a row_factory on turso connections; use turso.Row instead

What it means

pyturso's Connection/Cursor are not subclasses of the stdlib sqlite3 module, so sqlite3.Row cannot wrap turso result rows. When a fetch applies a row_factory that is a subclass of sqlite3.Row, constructing it fails with TypeError, and _reject_stdlib_row_factory replaces that with an explicit message directing you to turso's own Row type (lib.py:917). The error surfaces at fetch time (fetchone/fetchmany/fetchall/iteration), not at assignment time.

Source

Thrown at bindings/python/turso/lib.py:215

    """
    Run PyTursoStatement.step() once handling potential async IO loops.
    """
    while True:
        status = stmt.step()
        if status == Status.Io:
            stmt.run_io()
            if extra_io:
                extra_io()
            continue
        return status


def _reject_stdlib_row_factory(rf: Any) -> None:
    stdlib_sqlite3 = sys.modules.get("sqlite3")
    if stdlib_sqlite3 is None:
        return
    if isinstance(rf, type) and issubclass(rf, stdlib_sqlite3.Row):
        raise TypeError("sqlite3.Row is not supported as a row_factory on turso connections; use turso.Row instead")


@dataclass
class _Prepared:
    stmt: PyTursoStatement
    tail_index: int
    has_columns: bool
    column_names: tuple[str, ...]


# Connection goes FIRST
class Connection:
    """
    A connection to a Turso (SQLite-compatible) database.

    Similar to sqlite3.Connection with a subset of features focusing on DB-API 2.0.
    """

View on GitHub (pinned to bad083fafb)

Solutions

  1. Use turso's row type instead: `from turso import Row; conn.row_factory = Row` — it provides the same name-based access over turso rows
  2. If you don't need mapping-style access, leave row_factory as None and use index-based tuple access
  3. For shared code supporting both drivers, select the factory conditionally based on the connection type

Example fix

# before
import sqlite3
conn = turso.connect("db")
conn.row_factory = sqlite3.Row  # explodes at fetch time
for row in conn.execute("SELECT id, name FROM t"):
    print(row["name"])

# after
from turso import Row
conn = turso.connect("db")
conn.row_factory = Row
for row in conn.execute("SELECT id, name FROM t"):
    print(row["name"])
Defensive patterns

Strategy: type-guard

Validate before calling

import sqlite3

def pick_row_factory(conn):
    """Return a row factory compatible with the connection's driver."""
    driver = type(conn).__module__
    if driver.startswith("turso"):
        from turso import Row
        return Row
    return sqlite3.Row

conn.row_factory = pick_row_factory(conn)

Type guard

import sqlite3

def row_factory_supported(rf) -> bool:
    """False when rf is a stdlib sqlite3.Row subclass, which turso rejects."""
    stdlib_row = getattr(sqlite3, "Row", None)
    return not (
        isinstance(rf, type)
        and stdlib_row is not None
        and issubclass(rf, stdlib_row)
    )

Try / catch

try:
    row = cur.fetchone()
except TypeError as e:
    if "sqlite3.Row is not supported" in str(e):
        conn.row_factory = None  # or turso Row; then re-fetch
    else:
        raise

Prevention

When it happens

Trigger: `import sqlite3` then `conn.row_factory = sqlite3.Row` on a turso connection (or `cur.row_factory = sqlite3.Row`) followed by any row fetch. Typical when porting sqlite3/aiosqlite code: `for row in cur.execute("SELECT ...")` after setting the factory.

Common situations: Migrating an existing sqlite3 project to pyturso; shared helper modules or ORMs that set sqlite3.Row unconditionally; tutorial code copied from the sqlite3 docs; aiosqlite wrappers that inject sqlite3.Row.

Related errors


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/0dc57d2bc8ae8765. Report an issue: GitHub.