tursodatabase/turso · error · ProgrammingError
batch mode must be one of {sorted(_BATCH_MODES)} or None, go
Error message
batch mode must be one of {sorted(_BATCH_MODES)} or None, got {mode!r} What it means
Serverless Python SDK equivalent of the batch-mode validation: _batch_begin_sql maps the batch() mode argument to a BEGIN statement via _BATCH_MODES, and raises ProgrammingError when the mode string matches no known mode. This fails before any HTTP request is made, so nothing reaches the server.
Source
Thrown at serverless/python/turso_serverless/connection.py:73
"concurrent": "BEGIN CONCURRENT",
}
_TRANSACTION_CONTROL_KEYWORDS = {
"BEGIN",
"COMMIT",
"END",
"ROLLBACK",
"SAVEPOINT",
"RELEASE",
}
def _batch_begin_sql(mode: str | None) -> str | None:
if mode is None:
return None
begin_sql = _BATCH_MODES.get(str(mode).lower())
if begin_sql is None:
raise ProgrammingError(
f"batch mode must be one of {sorted(_BATCH_MODES)} or None, got {mode!r}"
)
return begin_sql
def _normalize_batch_statements(
statements: Iterable[Any],
) -> list[tuple[str, Sequence[Any] | Mapping[str, Any]]]:
"""Normalize batch input to (sql, parameters) pairs. Accepts SQL
strings and (sql, parameters) pairs, like the JavaScript driver."""
normalized = []
for index, statement in enumerate(statements):
if isinstance(statement, str):
normalized.append((statement, ()))
continue
if (
isinstance(statement, (tuple, list))
and len(statement) == 2View on GitHub (pinned to c1e5928725)
Solutions
- Use a mode exactly listed in the error message (matching is done on str(mode).lower()), or None.
- Strip whitespace and lowercase your mode value before passing it.
- Pass enum .value (a str) not the enum instance if wrapping modes in an Enum.
- Consult _BATCH_MODES in serverless/python/turso_serverless/connection.py for the authoritative set for your installed version.
Example fix
# before await conn.batch(stmts, mode="IMMEDIATE ") # after await conn.batch(stmts, mode="immediate")
Defensive patterns
Strategy: validation
Validate before calling
from turso_serverless.connection import _BATCH_MODES
mode = str(mode).strip().lower() if mode is not None else None
if mode is not None and mode not in _BATCH_MODES:
raise ValueError(f"unsupported batch mode {mode!r}; choose from {sorted(_BATCH_MODES)}") Type guard
def is_valid_batch_mode(mode: object) -> bool:
from turso_serverless.connection import _BATCH_MODES
return mode is None or str(mode).lower() in _BATCH_MODES Try / catch
try:
await conn.batch(stmts, mode=mode)
except ProgrammingError as e:
log.warning("bad batch mode %r: %s", mode, e)
await conn.batch(stmts, mode=None) Prevention
- Copy mode names exactly from the SDK docs / _BATCH_MODES.
- Normalize config-supplied modes with .strip().lower().
- Pass enum .value, not the enum object.
- Re-verify supported modes after SDK upgrades.
When it happens
Trigger: Calling Connection.batch(statements, mode=...) on turso_serverless with an unrecognized mode string such as 'BEGIN', 'write', 'transaction', or an enum whose str() isn't a mode name.
Common situations: Copying mode names from other database drivers (psycopg isolation levels, sqlite3 transaction_mode), typos/case-plus-whitespace issues, and SDK version drift where documented modes changed.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- batch statement {index} must be a SQL string or a (sql, para
- batch mode must be one of {sorted(_BATCH_MODES)} or None, go
- batch statement {index} must be a SQL string or a (sql, para
- Expected first argument to be an array of statements
- batch response does not have one result and one error per st
AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-31).
Data as JSON: /api/errors/cd6913d1dc7b6dc5.
Report an issue: GitHub.