{"record":{"id":"35b1137e635124a6","repo":"tursodatabase/turso","slug":"batch-mode-must-be-one-of-sorted-batch-modes-o","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":"bindings/python/turso/lib.py","lineNumber":226,"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: Optional[str]) -> Optional[str]:\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.\"\"\"\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":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/tursodatabase/turso/blob/c1e59287258d99b309e362a63f48822256e2f65f/bindings/python/turso/lib.py#L208-L244","documentation":"In the embedded Python bindings, Connection.batch() accepts an optional mode naming the transaction-control BEGIN statement for the batch. The mode string is looked up in the _BATCH_MODES dict (case-insensitively); if it isn't one of the recognized names, _batch_begin_sql raises a ProgrammingError before any SQL runs. The error text lists the valid modes, so it is purely a client-side argument-validation error.","triggerScenarios":"Calling batch(statements, mode=...) with a mode string not in _BATCH_MODES, e.g. mode=\"BEGIN\", mode=\"transaction\", mode=\"immediate \" with stray characters, or passing a non-string type that lowercases to an unknown name.","commonSituations":"Porting code from another driver whose batch/transaction API uses different mode vocabulary ('deferred'/'immediate'/'exclusive' vs this library's names), typos like 'IMMEDIATE  ' or 'write', and passing an enum member whose str() isn't a plain mode name.","solutions":["Use exactly one of the modes printed in the message (lowercase-insensitive): e.g. 'deferred', 'immediate', 'exclusive' as supported by _BATCH_MODES, or None for no transaction.","Normalize before passing: str(mode).strip().lower(), since matching is done on the lowercased string but whitespace/typos still fail.","If you have a custom enum, pass mode.value rather than the enum object.","Check the installed version's _BATCH_MODES dict (bindings/python/turso/lib.py) if upgrading — supported modes may differ from docs."],"exampleFix":"# before\nconn.batch(stmts, mode=\"BEGIN\")\n# after\nconn.batch(stmts, mode=\"deferred\")  # or mode=None","handlingStrategy":"validation","validationCode":"_VALID_MODES = {\"deferred\", \"immediate\", \"exclusive\"}  # intersect with _BATCH_MODES for your version\nmode = str(mode).strip().lower() if mode is not None else None\nassert mode is None or mode in _VALID_MODES, f\"bad batch mode: {mode!r}\"","typeGuard":"def is_valid_batch_mode(mode: object) -> bool:\n    from turso.lib import _BATCH_MODES\n    return mode is None or str(mode).lower() in _BATCH_MODES","tryCatchPattern":"try:\n    conn.batch(stmts, mode=mode)\nexcept ProgrammingError as e:\n    log.warning(\"bad batch mode %r: %s\", mode, e)\n    conn.batch(stmts, mode=None)  # safe fallback: no wrapping transaction","preventionTips":["Only pass literal mode strings from _BATCH_MODES or None.","Lowercase/strip any user- or config-supplied mode.","If wrapping modes in an Enum, pass .value.","Re-check _BATCH_MODES after SDK upgrades."],"tags":["python","api-misuse","validation","batch"],"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-14T00:17:10.932Z"}