{"record":{"id":"55a077450357b84c","repo":"langchain-ai/deepagents","slug":"cannot-configure-a-closed-mcp-session-manager","errorCode":null,"errorMessage":"Cannot configure a closed MCP session manager","messagePattern":"Cannot configure a closed MCP session manager","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/mcp_tools.py","lineNumber":670,"sourceCode":"    def configure(self, connections: dict[str, Connection]) -> None:\n        \"\"\"Set or validate the connection configs used by this manager.\n\n        When no sessions exist yet, `connections` overwrites the stored\n        configs unconditionally. Once any session has been created, the\n        new `connections` must produce the same signature as the stored\n        ones — otherwise this raises to prevent rebinding live sessions\n        to different transports or auth providers.\n\n        Args:\n            connections: Connection configs keyed by server name.\n\n        Raises:\n            RuntimeError: If the manager is closed or reconfigured\n                incompatibly after sessions already exist.\n        \"\"\"\n        if self._closed:\n            msg = \"Cannot configure a closed MCP session manager\"\n            raise RuntimeError(msg)\n\n        if not self._entries:\n            self._connections = dict(connections)\n            return\n\n        if _connections_signature(self._connections) != _connections_signature(\n            connections,\n        ):\n            msg = \"Cannot reconfigure MCP session manager after sessions are active\"\n            raise RuntimeError(msg)\n        self._connections = dict(connections)\n\n    async def get_session(self, server_name: str) -> ClientSession:\n        \"\"\"Return a cached session for `server_name`, creating it lazily.\"\"\"\n        entry = self._entries.get(server_name)\n        if entry is not None:\n            return entry.session\n","sourceCodeStart":652,"sourceCodeEnd":688,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/mcp_tools.py#L652-L688","documentation":"MCPSessionManager.configure() raises RuntimeError if the manager has been closed (cleanup ran). After close, the manager no longer accepts new connection configs.","triggerScenarios":"Calling configure() on a manager after close()/cleanup; reconfiguring inside shutdown paths such as _fail_closed_disable_tracing after cleanup already ran.","commonSituations":"Long-lived app where an atexit/finally handler closed the manager and later code (e.g. LangSmith secret-redaction config) tries to reconfigure; tests reusing a closed fixture.","solutions":["Reorder code so configure() is called before close()/cleanup","Create a fresh MCPSessionManager instance if reconfiguration is needed after close","Guard the configure call with a check that the manager is not closed"],"exampleFix":"// before\nawait manager.close()\nawait manager.configure(connections)  # raises\n// after\nawait manager.configure(connections)\nawait manager.close()","handlingStrategy":"try-catch","validationCode":"if manager.is_closed():  # or track _closed yourself\n    manager = MCPSessionManager()","typeGuard":null,"tryCatchPattern":"try:\n    await manager.configure(connections)\nexcept RuntimeError as e:\n    if 'closed' in str(e):\n        manager = MCPSessionManager()\n        await manager.configure(connections)\n    else:\n        raise","preventionTips":["Configure managers once at startup, before any session use","Keep a single owner responsible for the manager lifecycle","Avoid reconfiguring from shutdown/atexit hooks"],"tags":["mcp","lifecycle","runtime-error"],"backgroundTag":"manager-already-closed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}