{"record":{"id":"a601ab9239c2367c","repo":"PrefectHQ/fastmcp","slug":"client-is-not-connected-use-the-async-with-clien","errorCode":null,"errorMessage":"Client is not connected. Use the 'async with client:' context manager first.","messagePattern":"Client is not connected\\. Use the 'async with client:' context manager first\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/client/client.py","lineNumber":654,"sourceCode":"    def _reset_session_state(self, full: bool = False) -> None:\n        \"\"\"Reset session state after disconnect or cancellation.\n\n        Args:\n            full: If True, also resets session_task and nesting_counter.\n                  Use full=True for cancellation cleanup where the session\n                  task was started but never completed normally.\n        \"\"\"\n        self._session_state.session = None\n        self._session_state.initialize_result = None\n        if full:\n            self._session_state.session_task = None\n            self._session_state.nesting_counter = 0\n\n    @property\n    def session(self) -> ClientSession:\n        \"\"\"Get the current active session. Raises RuntimeError if not connected.\"\"\"\n        if self._session_state.session is None:\n            raise RuntimeError(\n                \"Client is not connected. Use the 'async with client:' context manager first.\"\n            )\n\n        return self._session_state.session\n\n    @property\n    def prior_discover(self) -> mcp_types.DiscoverResult | None:\n        \"\"\"The configured result to adopt when `mode` pins a modern version.\"\"\"\n        return self._prior_discover\n\n    @property\n    def initialize_result(self) -> mcp_types.InitializeResult | None:\n        \"\"\"Get the result of the initialization request.\n\n        `None` on a modern (`server/discover`) connection, which negotiates via a\n        `DiscoverResult` rather than an `InitializeResult`. Use `protocol_version`,\n        `server_info`, `server_capabilities`, and `instructions` for era-neutral\n        access to the negotiated server metadata.","sourceCodeStart":636,"sourceCodeEnd":672,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/client.py#L636-L672","documentation":"FastMCP's Client only holds an active MCP session between entering and exiting its async context manager. The `session` property raises this RuntimeError when accessed outside that window because there is no underlying ClientSession to return. It guards low-level session APIs against use on a disconnected client.","triggerScenarios":"Accessing `client.session` (directly or via session-level methods) before `async with client:` is entered, after the context has exited, or after a failed/closed connection reset the session state.","commonSituations":"Caching `client.session` in a variable and reusing it after the `async with` block ended; calling client methods on a constructed-but-never-entered client; an earlier connection failure left the session as None.","solutions":["Wrap usage in `async with client:` before touching client.session","Use high-level client methods (list_tools, call_tool, ...) inside the context manager instead of caching the session","Keep all calls within the same connection scope (e.g. after manual initialize())","Verify a prior `async with` block didn't already exit before the call"],"exampleFix":"// before\nclient = Client(transport)\nresult = await client.session.list_tools()  # RuntimeError\n\n// after\nclient = Client(transport)\nasync with client:\n    result = await client.list_tools()  # or client.session.list_tools()","handlingStrategy":"try-catch","validationCode":"def ensure_connected(client) -> None:\n    if client._session_state.session is None:\n        raise RuntimeError(\"Enter 'async with client:' before using the session\")","typeGuard":null,"tryCatchPattern":"try:\n    session = client.session\nexcept RuntimeError as e:\n    if \"not connected\" in str(e):\n        async with client:\n            session = client.session\n    else:\n        raise","preventionTips":["Always access session-dependent APIs inside `async with client:`","Never cache client.session beyond the context manager's lifetime","Prefer high-level client methods over raw session access"],"tags":["python","async","lifecycle","client-session"],"backgroundTag":"client-not-connected","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}