{"record":{"id":"8196722d0439338d","repo":"agentscope-ai/agentscope","slug":"either-client-gen-or-session-must-be-provided-but","errorCode":null,"errorMessage":"Either client_gen or session must be provided, but not both.","messagePattern":"Either client_gen or session must be provided, but not both\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/agentscope/tool/_adapters.py","lineNumber":283,"sourceCode":"        self.is_read_only = False\n        if tool.annotations and hasattr(tool.annotations, \"readOnlyHint\"):\n            self.is_read_only = tool.annotations.readOnlyHint or False\n\n        # Store MCP tool and connection info\n        self._tool = tool\n        self._client_gen = client_gen\n        self._session = session\n\n        if timeout:\n            self._timeout = timedelta(seconds=timeout)\n        else:\n            self._timeout = None\n\n        # Validate that either client_gen or session is provided\n        if (client_gen is None and session is None) or (\n            client_gen is not None and session is not None\n        ):\n            raise ValueError(\n                \"Either client_gen or session must be provided, but not both.\",\n            )\n\n    async def check_permissions(\n        self,\n        *_args: Any,\n        **_kwargs: Any,\n    ) -> PermissionDecision:\n        \"\"\"Check permissions for the MCP tool usage.\n\n        Default implementation allows all operations.\n\n        Returns:\n            `PermissionDecision`:\n                Permission decision (default: ask for confirmation).\n        \"\"\"\n        if self.is_read_only:\n            return PermissionDecision(","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/tool/_adapters.py#L265-L301","documentation":"This adapter class (MCP-related, in tool/_adapters.py) requires exactly one of client_gen or session in __init__; providing neither or both raises ValueError.","triggerScenarios":"Constructing the adapter with both an AsyncExitStack-managed session and a client generator, or with neither (relying on some other connection mechanism).","commonSituations":"Migrating MCP client setup code where a session was previously created externally, then also passing client_gen; or refactoring removed the client_gen argument entirely.","solutions":["Pass only client_gen (an async factory producing an async-exit-stack pair) for lazily managed connections","Or pass only a pre-established session for externally managed lifetimes","Remove the redundant argument from your constructor call"],"exampleFix":"# before\nadapter = Adapter(client_gen=gen, session=sess)\n# after\nadapter = Adapter(client_gen=gen)","handlingStrategy":"validation","validationCode":"assert (client_gen is None) != (session is None)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Choose one lifecycle model: lazy client_gen or externally managed session","Write a small factory wrapper so call sites can't pass both"],"tags":["mcp","constructor","validation","mutually-exclusive"],"backgroundTag":"invalid-argument-value","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}