{"record":{"id":"e7cae99a0b85b218","repo":"tursodatabase/turso","slug":"invalid-pipeline-response-e","errorCode":null,"errorMessage":"invalid pipeline response: {e}","messagePattern":"invalid pipeline response: (.+?)","errorType":"exception","errorClass":"ProtocolError","httpStatus":null,"severity":"error","filePath":"serverless/python/turso_serverless/session.py","lineNumber":238,"sourceCode":"    def _update_stream(self, baton: Optional[str], base_url: Optional[str]) -> None:\n        self._baton = baton\n        if base_url:\n            self._base_url = normalize_url(base_url)\n\n    def execute_pipeline(self, requests: list[dict], track_autocommit: bool = True) -> list[dict]:\n        \"\"\"Execute a pipeline (section 5). When `track_autocommit` is set, a\n        `get_autocommit` request is appended and its answer refreshes the\n        cached transaction state; the returned results cover only the\n        caller's requests.\"\"\"\n        reqs = list(requests)\n        if track_autocommit:\n            reqs.append({\"type\": \"get_autocommit\"})\n        raw = self._post(\"/v3/pipeline\", {\"baton\": self._baton, \"requests\": reqs})\n        try:\n            resp: dict[str, Any] = json.loads(raw)\n        except ValueError as e:\n            self._reset_stream()\n            raise ProtocolError(f\"invalid pipeline response: {e}\") from None\n        self._update_stream(resp.get(\"baton\"), resp.get(\"base_url\"))\n        results = resp.get(\"results\") or []\n        # The protocol guarantees one result per request (section 5.2); a\n        # mismatch would misattribute results to the wrong requests.\n        if len(results) != len(reqs):\n            raise ProtocolError(\n                f\"pipeline response has {len(results)} results for {len(reqs)} requests\"\n            )\n        if track_autocommit:\n            result = results.pop()\n            if result.get(\"type\") == \"error\":\n                raise _server_error(result.get(\"error\"))\n            response = result.get(\"response\") or {}\n            if response.get(\"type\") != \"get_autocommit\" or not isinstance(\n                response.get(\"is_autocommit\"), bool\n            ):\n                raise ProtocolError(\n                    f\"expected get_autocommit result in pipeline response, got {response}\"","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/serverless/python/turso_serverless/session.py#L220-L256","documentation":"ProtocolError raised by Session.execute_pipeline (session.py:234-238) when the /v3/pipeline response body fails JSON parsing outright. The stream is reset before the error is raised. execute_pipeline backs executescript() and the connection's autocommit tracking, so the error typically surfaces from an executescript call or as a secondary failure while executing statements.","triggerScenarios":"The pipeline endpoint returns an empty body, an HTML error page, or truncated JSON — same corruption class as errors 287/288 but on /v3/pipeline; also seen when a URL points at a server that does not implement the pipeline endpoint.","commonSituations":"Intermediaries (gateways, CDNs) rewriting or emptying bodies; version mismatch with a server lacking /v3/pipeline support; network truncation of large script responses.","solutions":["Verify the endpoint implements /v3/pipeline and that client/server versions match","Bypass response-mutating intermediaries","Retry on the fresh stream the reset created; upgrade the driver if it persists"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from turso_serverless.protocol import ProtocolError\n\ntry:\n    conn.executescript(script)\nexcept ProtocolError as e:\n    if not str(e).startswith(\"invalid pipeline response\"):\n        raise\n    conn = connect(URL, auth_token=TOKEN)  # stream was reset; reconnect and retry once\n    conn.executescript(script)","preventionTips":["Confirm the endpoint implements /v3/pipeline before adding custom infrastructure in front of it","Keep executescript inputs on the smaller side; very large scripts amplify truncation risk","Pin client/server versions in deployment manifests"],"tags":["python","protocol","pipeline","json","response-parsing"],"backgroundTag":"malformed-server-response","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}