{"record":{"id":"95480f05febce7ff","repo":"langchain-ai/langgraph","slug":"protocol-transport-is-closed","errorCode":null,"errorMessage":"Protocol transport is closed.","messagePattern":"Protocol transport is closed\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/sdk-py/langgraph_sdk/stream/transport/http.py","lineNumber":73,"sourceCode":"        )\n        self._stream_url = (\n            stream_path or f\"/threads/{_quote_path_param(thread_id)}/stream/events\"\n        )\n        self._default_headers: dict[str, str] = dict(headers or {})\n        self._max_queue_size = max_queue_size\n        self._closed = False\n        self._event_streams: set[asyncio.Task[None]] = set()\n\n    async def send_command(self, command: dict[str, Any]) -> dict[str, Any] | None:\n        \"\"\"POST a command. Returns the response JSON, or `None` for 202/204.\n\n        Raises:\n            httpx.HTTPStatusError: server returned >= 400.\n            RuntimeError: the transport has been closed via `close()`.\n            RuntimeError: server returned a response missing the protocol envelope.\n        \"\"\"\n        if self._closed:\n            raise RuntimeError(\"Protocol transport is closed.\")\n        # Merge default headers first so content-type always wins.\n        merged_headers = {**self._default_headers, \"content-type\": \"application/json\"}\n        response = await self._client.post(\n            self._commands_url,\n            content=orjson.dumps(command),\n            headers=merged_headers,\n        )\n        response.raise_for_status()\n        if response.status_code in (202, 204):\n            return None\n        if not response.content:\n            raise RuntimeError(\"Protocol command did not return a valid response.\")\n        try:\n            payload = orjson.loads(response.content)\n        except orjson.JSONDecodeError as err:\n            raise RuntimeError(\n                \"Protocol command did not return a valid response.\"\n            ) from err","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/langchain-ai/langgraph/blob/38031739e551638e373fb553453256c23feeb41f/libs/sdk-py/langgraph_sdk/stream/transport/http.py#L55-L91","documentation":"Lifecycle guard on the async HTTP protocol transport: send_command (and other operations) check the _closed flag set by close(). The error means a command was posted after the transport was explicitly closed, e.g. sending run.start or join on a stream session that was already torn down.","triggerScenarios":"Thrown at libs/sdk-py/langgraph_sdk/stream/transport/http.py:73 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Open a new stream session (new transport) instead of reusing one that has been closed","Ensure you do not call close() (or exit the context manager) before issuing further commands","Structure code so all commands are sent within the stream's lifetime (inside the 'with'/'async with' block)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"38031739e551638e373fb553453256c23feeb41f","analyzedAt":"2026-08-26T18:02:49.312Z","contentChangedAt":"2026-08-26T18:02:49.312Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}