{"record":{"id":"10543fa2b2586e9f","repo":"tursodatabase/turso","slug":"batch-response-does-not-have-one-result-and-one-er-10543f","errorCode":null,"errorMessage":"batch response does not have one result and one error per step: {result}","messagePattern":"batch response does not have one result and one error per step: (.+?)","errorType":"error_code","errorClass":"ProtocolError","httpStatus":null,"severity":"error","filePath":"serverless/python/turso_serverless/connection.py","lineNumber":379,"sourceCode":"        result: dict,\n        stmts: list[tuple[str, Any]],\n        offset: int,\n        commit_index: int | None,\n        total_steps: int,\n    ) -> list[BatchResult]:\n        \"\"\"Decode a wire-level batch result into per-statement results, or\n        raise the error of the step that failed. Failures of the synthetic\n        BEGIN/COMMIT steps surface as-is. A ROLLBACK failure is attached to\n        that primary error as `rollback_error`.\"\"\"\n        step_results = result.get(\"step_results\")\n        step_errors = result.get(\"step_errors\")\n        if (\n            not isinstance(step_results, list)\n            or not isinstance(step_errors, list)\n            or len(step_results) != total_steps\n            or len(step_errors) != total_steps\n        ):\n            raise ProtocolError(\n                f\"batch response does not have one result and one error per step: {result}\"\n            )\n        # Decode the results of the statements that executed before looking\n        # at the errors, so a failure can still report what completed.\n        results: list[BatchResult | None] = [\n            Connection._decode_batch_statement_result(step_results[offset + i], sql)\n            for i, (sql, _parameters) in enumerate(stmts)\n        ]\n        rollback_error = None\n        if commit_index is not None and step_errors[commit_index + 1] is not None:\n            rollback_error = _classify_error(_server_error(step_errors[commit_index + 1]))\n        try:\n            Connection._raise_batch_step_error(step_errors, len(stmts), offset, commit_index, results)\n        except Exception as primary_error:\n            if rollback_error is not None:\n                primary_error.rollback_error = rollback_error\n            raise\n        if rollback_error is not None:","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/tursodatabase/turso/blob/c1e59287258d99b309e362a63f48822256e2f65f/serverless/python/turso_serverless/connection.py#L361-L397","documentation":"When decoding a batch response from the server, the SDK expects the response to carry step_results and step_errors arrays with exactly one entry per submitted statement. If either array is missing, not a list, or has a different length than the number of steps, _decode_batch_result raises ProtocolError — the server response violates the expected protocol (section 8.4) and cannot be trusted.","triggerScenarios":"A server (or proxy) returns a batch reply whose step_results/step_errors are absent, truncated, or longer than the submitted steps — e.g. after a server upgrade, a gateway mangling the JSON, or a genuine server bug.","commonSituations":"Version mismatch between client SDK and server pipeline protocol, responses through caching/transforming proxies, hitting a non-Turso endpoint that echoes unexpected JSON, or server-side truncation on very large batches.","solutions":["Upgrade the turso_serverless SDK and server together so protocol versions match.","Print the full response object in the message and check whether step_results/step_errors exist at all (indicates talking to the wrong endpoint/server).","Retry the batch — if a proxy corrupted the response, a fresh request may succeed.","Reduce batch size to rule out size-related server truncation.","Report to Turso support with the raw response if a current SDK against a current server still produces it."],"exampleFix":"# before\nresults = conn.batch(stmts)  # ProtocolError on shape mismatch\n# after\ntry:\n    results = conn.batch(stmts)\nexcept ProtocolError as e:\n    logger.error(\"malformed batch response: %s\", e)\n    results = retry_batch(stmts)  # or surface a clear client/server version mismatch","handlingStrategy":"retry","validationCode":"def batch_response_well_formed(result: dict, total_steps: int) -> bool:\n    sr, se = result.get(\"step_results\"), result.get(\"step_errors\")\n    return (\n        isinstance(sr, list) and isinstance(se, list)\n        and len(sr) == total_steps and len(se) == total_steps\n    )","typeGuard":null,"tryCatchPattern":"try:\n    results = conn.batch(stmts)\nexcept ProtocolError as e:\n    log.error(\"malformed batch response: %s\", e)\n    results = conn.batch(stmts)  # retry once; persistent failure => version mismatch","preventionTips":["Keep SDK and server versions aligned.","Avoid proxies that rewrite JSON bodies.","Make batched statements idempotent so retries are safe.","Report persistent shape violations to Turso with the raw response."],"tags":["python","protocol","server-response","batch","serverless"],"backgroundTag":"malformed-server-response","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"}