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

  1. List the exact registered names first: GET /claude-code/plugins returns all plugins with their exact slugs — use that name verbatim.
  2. Check casing (names are lowercase kebab-case), trailing whitespace, and URL-encoding of the path segment.
  3. 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

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


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/f262ffb0416f2b0f. Report an issue: GitHub.