{"record":{"id":"cd6913d1dc7b6dc5","repo":"tursodatabase/turso","slug":"batch-mode-must-be-one-of-sorted-batch-modes-o-cd6913","errorCode":null,"errorMessage":"batch mode must be one of {sorted(_BATCH_MODES)} or None, got {mode!r}","messagePattern":"batch mode must be one of (.+?) or None, got (.+?)","errorType":"validation","errorClass":"ProgrammingError","httpStatus":null,"severity":"error","filePath":"serverless/python/turso_serverless/connection.py","lineNumber":73,"sourceCode":"    \"concurrent\": \"BEGIN CONCURRENT\",\n}\n\n_TRANSACTION_CONTROL_KEYWORDS = {\n    \"BEGIN\",\n    \"COMMIT\",\n    \"END\",\n    \"ROLLBACK\",\n    \"SAVEPOINT\",\n    \"RELEASE\",\n}\n\n\ndef _batch_begin_sql(mode: str | None) -> str | None:\n    if mode is None:\n        return None\n    begin_sql = _BATCH_MODES.get(str(mode).lower())\n    if begin_sql is None:\n        raise ProgrammingError(\n            f\"batch mode must be one of {sorted(_BATCH_MODES)} or None, got {mode!r}\"\n        )\n    return begin_sql\n\n\ndef _normalize_batch_statements(\n    statements: Iterable[Any],\n) -> list[tuple[str, Sequence[Any] | Mapping[str, Any]]]:\n    \"\"\"Normalize batch input to (sql, parameters) pairs. Accepts SQL\n    strings and (sql, parameters) pairs, like the JavaScript driver.\"\"\"\n    normalized = []\n    for index, statement in enumerate(statements):\n        if isinstance(statement, str):\n            normalized.append((statement, ()))\n            continue\n        if (\n            isinstance(statement, (tuple, list))\n            and len(statement) == 2","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/tursodatabase/turso/blob/c1e59287258d99b309e362a63f48822256e2f65f/serverless/python/turso_serverless/connection.py#L55-L91","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nawait conn.batch(stmts, mode=\"IMMEDIATE \")\n# after\nawait conn.batch(stmts, mode=\"immediate\")","handlingStrategy":"validation","validationCode":"from turso_serverless.connection import _BATCH_MODES\nmode = str(mode).strip().lower() if mode is not None else None\nif mode is not None and mode not in _BATCH_MODES:\n    raise ValueError(f\"unsupported batch mode {mode!r}; choose from {sorted(_BATCH_MODES)}\")","typeGuard":"def is_valid_batch_mode(mode: object) -> bool:\n    from turso_serverless.connection import _BATCH_MODES\n    return mode is None or str(mode).lower() in _BATCH_MODES","tryCatchPattern":"try:\n    await conn.batch(stmts, mode=mode)\nexcept ProgrammingError as e:\n    log.warning(\"bad batch mode %r: %s\", mode, e)\n    await conn.batch(stmts, mode=None)","preventionTips":["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."],"tags":["python","api-misuse","validation","batch","serverless"],"backgroundTag":"invalid-argument-value","analyzedSha":"c1e59287258d99b309e362a63f48822256e2f65f","analyzedAt":"2026-08-31T11:17:35.598Z","contentChangedAt":"2026-08-31T11:17:35.598Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}