BerriAI/litellm · warning · HTTPException
Plugin '{plugin_name}' not found
Error message
Plugin '{plugin_name}' not found What it means
404 from get_plugin (GET /claude-code/plugins/{plugin_name}) when find_unique on the name returns no row. Lookup is by exact, case-sensitive name match against the kebab-case primary key; trailing slashes, spaces, URL-encoding artifacts, or wrong casing all miss. Disabled plugins are still returned — only a truly absent name 404s.
Source
Thrown at litellm/proxy/anthropic_endpoints/claude_code_endpoints/claude_code_marketplace.py:429
):
"""
Get details of a specific plugin.
Parameters:
- plugin_name: The name of the plugin
Returns:
Plugin details including source and metadata.
"""
try:
prisma_client: Final = await _get_prisma_client()
plugin: Final[_PluginRecord | None] = await ClaudeCodePluginRepository(prisma_client).table.find_unique(
where={"name": plugin_name}
)
if not plugin:
raise HTTPException(
status_code=404,
detail={"error": f"Plugin '{plugin_name}' not found"},
)
manifest: Final[Mapping[str, object]] = json.loads(plugin.manifest_json or "{}") if plugin.manifest_json else {}
return {
"id": plugin.id,
"name": plugin.name,
"version": plugin.version,
"description": plugin.description,
"source": manifest.get("source"),
"author": manifest.get("author"),
"homepage": manifest.get("homepage"),
"keywords": manifest.get("keywords"),
"category": manifest.get("category"),
"enabled": plugin.enabled,
"created_at": plugin.created_at.isoformat() if plugin.created_at else None,View on GitHub (pinned to 77b7c6c40c)
Solutions
- List the exact registered names first: GET /claude-code/plugins returns all plugins with their exact slugs — use that name verbatim.
- Check casing (names are lowercase kebab-case), trailing whitespace, and URL-encoding of the path segment.
- If the plugin was deleted by mistake, re-register it with POST /claude-code/plugins.
Example fix
# before curl http://localhost:4000/claude-code/plugins/Data_Cleaner # -> 404 Plugin 'Data_Cleaner' not found # after curl http://localhost:4000/claude-code/plugins # list exact names curl http://localhost:4000/claude-code/plugins/data-cleaner
Defensive patterns
Strategy: validation
Validate before calling
plugins = client.get(f"{base}/claude-code/plugins", headers=hdr).json()["plugins"]
names = {p["name"] for p in plugins}
if plugin_name not in names:
raise KeyError(f"{plugin_name!r} not registered; available: {sorted(names)}") Try / catch
resp = client.get(f"{base}/claude-code/plugins/{plugin_name}", headers=hdr)
if resp.status_code == 404:
# not an error in discovery flows - plugin simply absent
return None
resp.raise_for_status()
return resp.json() Prevention
- Resolve names through the list endpoint instead of constructing them from titles.
- Normalize to the exact registered kebab-case slug everywhere (config, scripts, docs).
When it happens
Trigger: GET /claude-code/plugins/Data_Cleaner when the plugin was registered as "data-cleaner"; GET /claude-code/plugins/my-plugin%2F when a slash got encoded into the path; requesting a plugin that was deleted via DELETE /claude-code/plugins/{name} earlier.
Common situations: Casing/underscore mismatches between what a user typed and the registered slug; referencing a plugin deleted by another admin; copy-pasting a name with a trailing newline/space from a doc; assuming enable/disable hides the plugin from GET.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- 404
- Vector store with ID {data.vector_store_id} not found
- Prompt version '{prompt_version_id}' not found
- Skill not found: {skill_id}
- DB not connected. This endpoint needs a database; set DATABA
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/f262ffb0416f2b0f.
Report an issue: GitHub.