{"record":{"id":"41cd08bbebe66f16","repo":"tursodatabase/turso","slug":"expected-batch-result-in-pipeline-response-got-r","errorCode":null,"errorMessage":"expected batch result in pipeline response, got {response}","messagePattern":"expected batch result in pipeline response, got (.+?)","errorType":"error_code","errorClass":"ProtocolError","httpStatus":null,"severity":"error","filePath":"serverless/python/turso_serverless/session.py","lineNumber":330,"sourceCode":"            self._refresh_autocommit()\n        else:\n            self._autocommit = decoder.probe_executed\n        if decoder.step_error is not None:\n            raise decoder.step_error\n        return decoder.result\n\n    def execute_batch(self, steps: list[dict]) -> dict:\n        \"\"\"Execute a batch request on the pipeline endpoint (section 6.2)\n        and return its raw result: `step_results` and `step_errors` arrays\n        with one entry per step. Step failures are reported in those\n        arrays, not raised here.\"\"\"\n        results = self.execute_pipeline([{\"type\": \"batch\", \"batch\": {\"steps\": steps}}])\n        result = results[0]\n        if result.get(\"type\") == \"error\":\n            raise _server_error(result.get(\"error\"))\n        response = result.get(\"response\") or {}\n        if response.get(\"type\") != \"batch\" or not isinstance(response.get(\"result\"), dict):\n            raise ProtocolError(f\"expected batch result in pipeline response, got {response}\")\n        return response[\"result\"]\n\n    def close(self) -> None:\n        \"\"\"Close the stream (section 6.8). Errors are ignored: the stream\n        may already have expired.\"\"\"\n        if self._baton is not None:\n            try:\n                self.execute_pipeline([{\"type\": \"close\"}], track_autocommit=False)\n            except Exception:\n                pass\n        self._reset_stream()\n","sourceCodeStart":312,"sourceCodeEnd":342,"githubUrl":"https://github.com/tursodatabase/turso/blob/c1e59287258d99b309e362a63f48822256e2f65f/serverless/python/turso_serverless/session.py#L312-L342","documentation":"Session.execute_batch sends a batch step through the pipeline and expects the reply entry to be type=\"batch\" with a dict-shaped result. If the response entry has any other type or a missing/non-dict result, execute_batch raises ProtocolError — the server answered, but not with a batch result this client can decode.","triggerScenarios":"Calling execute_batch against a server whose pipeline reply for the batch step is an unexpected shape (empty response object, different type tag), after server upgrades/downgrades, or when the response was altered in transit.","commonSituations":"Client/server protocol version mismatch, load balancers or proxies rewriting responses, and pointing the SDK at an endpoint that speaks a different pipeline revision.","solutions":["Align SDK and server versions; the batch response shape (section 6.2/8.4) changed across protocol revisions.","Log the full `response` object embedded in the message to see what the server actually returned.","Bypass proxies/gateways to rule out response rewriting.","Retry the request; if persistent, capture the payload and report to Turso support."],"exampleFix":"# before\nresult = session.execute_batch(steps)  # ProtocolError: got {'type': 'ok'}\n# after\ntry:\n    result = session.execute_batch(steps)\nexcept ProtocolError as e:\n    logger.error(\"unexpected pipeline reply: %s\", e)\n    raise RuntimeError(\"server protocol mismatch — upgrade turso_serverless and server together\") from e","handlingStrategy":"try-catch","validationCode":"def batch_reply_well_formed(entry: dict) -> bool:\n    resp = entry.get(\"response\") or {}\n    return entry.get(\"type\") != \"error\" and resp.get(\"type\") == \"batch\" and isinstance(resp.get(\"result\"), dict)","typeGuard":null,"tryCatchPattern":"try:\n    result = session.execute_batch(steps)\nexcept ProtocolError as e:\n    log.error(\"unexpected pipeline reply: %s\", e)\n    raise RuntimeError(\"client/server pipeline protocol mismatch\") from e","preventionTips":["Upgrade turso_serverless SDK and the server together.","Log the full response embedded in the error for diagnosis.","Bypass proxies when verifying protocol behavior.","Ensure you are calling the correct pipeline endpoint revision (/v3/pipeline)."],"tags":["python","protocol","server-response","pipeline","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"}