From 8e989a063734b7524d1d3b7832332da69a92588c Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Thu, 29 Oct 2026 02:45:08 -0700 Subject: [PATCH] fix(claude-code): keep the no-database hint on skill_hub and warn that the remove step uninstalls plugins --- litellm/proxy/public_endpoints/public_endpoints.py | 5 +++-- tests/unit/proxy/public_endpoints/test_public_endpoints.py | 5 +++-- .../src/components/claude_code_plugins/skill_detail.test.tsx | 1 + .../src/components/claude_code_plugins/skill_detail.tsx | 4 +++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/litellm/proxy/public_endpoints/public_endpoints.py b/litellm/proxy/public_endpoints/public_endpoints.py index ddd00747eca..b8cdea0dea4 100644 --- a/litellm/proxy/public_endpoints/public_endpoints.py +++ b/litellm/proxy/public_endpoints/public_endpoints.py @@ -371,9 +371,9 @@ async def public_skill_hub(): from litellm.proxy.anthropic_endpoints.claude_code_endpoints.claude_code_marketplace import ( MANIFEST_FIELDS, get_installation_preference, - get_prisma_client, ) from litellm.proxy.common_utils.claude_code_marketplace_auth import marketplace_auth_required + from litellm.proxy.proxy_server import prisma_client from litellm.types.proxy.claude_code_endpoints import ( ListPluginsResponse, PluginListItem, @@ -381,8 +381,9 @@ async def public_skill_hub(): if marketplace_auth_required(): return ListPluginsResponse(plugins=[], count=0) + if prisma_client is None: + raise HTTPException(status_code=500, detail=CommonProxyErrors.db_not_connected_error.value) try: - prisma_client: Final = await get_prisma_client() plugins: Final = await _plugin_table(prisma_client).find_many(where={"enabled": True}) items: Final = [] for plugin in plugins: diff --git a/tests/unit/proxy/public_endpoints/test_public_endpoints.py b/tests/unit/proxy/public_endpoints/test_public_endpoints.py index 69b62626de7..160b81dc2b0 100644 --- a/tests/unit/proxy/public_endpoints/test_public_endpoints.py +++ b/tests/unit/proxy/public_endpoints/test_public_endpoints.py @@ -20,6 +20,7 @@ from litellm.proxy.auth.user_api_key_auth import user_api_key_auth from litellm.proxy.db.health_check_latest import LatestHealthCheckRow from litellm.proxy.public_endpoints import router from litellm.router_strategy.complexity_router.fuse_presets import get_fuse_presets +from litellm.types.proxy.common_proxy_errors import CommonProxyErrors from litellm.types.proxy.management_endpoints.model_management_endpoints import ( ModelGroupInfoProxy, ) @@ -1802,7 +1803,7 @@ def test_public_skill_hub_500_body_carries_no_exception_text() -> None: assert "db.internal" not in response.text -def test_public_skill_hub_without_a_database_answers_a_fixed_string_detail() -> None: +def test_public_skill_hub_without_a_database_answers_db_not_connected() -> None: app: Final = FastAPI() app.include_router(router) @@ -1813,4 +1814,4 @@ def test_public_skill_hub_without_a_database_answers_a_fixed_string_detail() -> response: Final = TestClient(app).get("/public/skill_hub") assert response.status_code == 500 - assert response.json() == {"detail": "Failed to list skills"} + assert response.json() == {"detail": CommonProxyErrors.db_not_connected_error.value} diff --git a/ui/litellm-dashboard/src/components/claude_code_plugins/skill_detail.test.tsx b/ui/litellm-dashboard/src/components/claude_code_plugins/skill_detail.test.tsx index f0f83846dab..951f30fc9cc 100644 --- a/ui/litellm-dashboard/src/components/claude_code_plugins/skill_detail.test.tsx +++ b/ui/litellm-dashboard/src/components/claude_code_plugins/skill_detail.test.tsx @@ -86,5 +86,6 @@ describe("SkillDetail marketplace setup", () => { expect(screen.queryByText(/\/plugin marketplace add/)).not.toBeInTheDocument(); expect(screen.getByText(/"Authorization": "Bearer "/)).toBeInTheDocument(); expect(screen.getByText("/plugin marketplace remove litellm")).toBeInTheDocument(); + expect(screen.getByText(/uninstalls the plugins you installed from it/)).toBeInTheDocument(); }); }); diff --git a/ui/litellm-dashboard/src/components/claude_code_plugins/skill_detail.tsx b/ui/litellm-dashboard/src/components/claude_code_plugins/skill_detail.tsx index 191e1e04299..658a0472699 100644 --- a/ui/litellm-dashboard/src/components/claude_code_plugins/skill_detail.tsx +++ b/ui/litellm-dashboard/src/components/claude_code_plugins/skill_detail.tsx @@ -239,7 +239,9 @@ const SkillDetail: React.FC = ({ skill, onBack }) => { <>

- If you added this marketplace before without a key, remove it first in Claude Code: + If you added this marketplace before without a key, remove it first in Claude Code. Removing it also + uninstalls the plugins you installed from it, so install them again from /plugin after you add the + snippet:

                   /plugin marketplace remove litellm