{"record":{"id":"8d0e93358589f79f","repo":"agentscope-ai/agentscope","slug":"an-mcp-named-mcp-record-name-r-already-exists-fo","errorCode":null,"errorMessage":"An MCP named {mcp_record.name!r} already exists for this user.","messagePattern":"An MCP named (.+?) already exists for this user\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/agentscope/app/storage/_sql/_storage.py","lineNumber":838,"sourceCode":"        return result.rowcount > 0\n\n    # ------------------------------------------------------------------\n    # Installed MCPs and skills\n    #\n    # ``(user_id, name)`` is unique on both tables. The pre-write lookup\n    # below turns the common case into the same ``ValueError`` the Redis\n    # backend raises; the constraint is the backstop that closes the\n    # read-then-write window between concurrent writers.\n    # ------------------------------------------------------------------\n\n    async def upsert_mcp(self, user_id: str, mcp_record: MCPRecord) -> str:\n        \"\"\"Create or update an installed-MCP record for *user_id*.\n\n        Same contract as :meth:`RedisStorage.upsert_mcp`.\n        \"\"\"\n        holder = await self.get_mcp_by_name(user_id, mcp_record.name)\n        if holder is not None and holder.id != mcp_record.id:\n            raise ValueError(\n                f\"An MCP named {mcp_record.name!r} already exists for \"\n                f\"this user.\",\n            )\n        mcp_record.user_id = user_id\n        await self._write_row(MCPRow, mcp_record)\n        return mcp_record.id\n\n    async def list_mcps(self, user_id: str) -> list[MCPRecord]:\n        \"\"\"Return every installed-MCP record for *user_id*.\"\"\"\n        from sqlalchemy import select\n\n        async with self._session() as sess:\n            rows = (\n                (\n                    await sess.execute(\n                        select(MCPRow).where(MCPRow.user_id == user_id),\n                    )\n                )","sourceCodeStart":820,"sourceCodeEnd":856,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/app/storage/_sql/_storage.py#L820-L856","documentation":"Raised by SQLStorage.upsert_mcp when creating or updating an installed-MCP record whose name is already taken by a different MCP record owned by the same user. Names are unique per user, so the check compares the existing record's id with the incoming mcp_record.id; a mismatch means a name collision with another record.","triggerScenarios":"Calling upsert_mcp(user_id, record) where record.name matches an existing MCP for that user but record.id differs (e.g. a new record reusing an existing name, or an update that changed the id).","commonSituations":"Re-installing an MCP under a name already registered for the user; copying MCP config between environments without preserving record ids; concurrent installs racing on the same name.","solutions":["Choose a unique name for the MCP record before upserting","If updating an existing MCP, load it first (get_mcp_by_name) and reuse its id and mutate fields instead of creating a new record","Delete the conflicting record (delete_mcp) before re-registering with the same name"],"exampleFix":"// before\nawait storage.upsert_mcp(user_id, MCPRecord(id=new_id, name=\"fs\"))  # name clash\n// after\nexisting = await storage.get_mcp_by_name(user_id, \"fs\")\nif existing:\n    existing.command = new_cmd\n    await storage.upsert_mcp(user_id, existing)  # same id -> update\nelse:\n    await storage.upsert_mcp(user_id, MCPRecord(name=\"fs\", ...))","handlingStrategy":"validation","validationCode":"existing = await storage.get_mcp_by_name(user_id, record.name)\nif existing is not None and existing.id != record.id:\n    record.name = f\"{record.name}-{uuid4().hex[:6]}\"  # or merge into existing","typeGuard":null,"tryCatchPattern":"try:\\n    await storage.upsert_mcp(user_id, rec)\\nexcept ValueError as e:\\n    if \\\"already exists\\\" in str(e): handle_name_collision(rec)\\n    else: raise","preventionTips":["Keep a registry of installed MCP names per user","Reuse existing record ids when updating"],"tags":["mcp","unique-constraint","sql-storage","upsert"],"backgroundTag":"duplicate-record-name","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}