{"record":{"id":"d149c9b02119c2d7","repo":"BerriAI/litellm","slug":"registration-failed-e","errorCode":null,"errorMessage":"Registration failed: {e}","messagePattern":"Registration failed: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"litellm/proxy/anthropic_endpoints/claude_code_endpoints/claude_code_marketplace.py","lineNumber":328,"sourceCode":"\n        return RegisterPluginResponse(\n            status=\"success\",\n            action=\"created\",\n            plugin=PluginResponse(\n                id=plugin.id,\n                name=plugin.name,\n                version=plugin.version,\n                description=plugin.description,\n                source=request.source,\n                enabled=plugin.enabled,\n            ),\n        )\n\n    except HTTPException:\n        raise\n    except Exception as e:\n        verbose_proxy_logger.exception(\"Error registering plugin: %s\", e)\n        raise HTTPException(\n            status_code=500,\n            detail={\"error\": f\"Registration failed: {e}\"},\n        )\n\n\n@router.get(\n    \"/claude-code/plugins\",\n    tags=[\"Claude Code Marketplace\"],\n    dependencies=[Depends(user_api_key_auth)],\n    response_model=ListPluginsResponse,\n)\nasync def list_plugins(\n    enabled_only: bool = False,\n    user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),\n):\n    \"\"\"\n    List all plugins in the marketplace.\n","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/anthropic_endpoints/claude_code_endpoints/claude_code_marketplace.py#L310-L346","documentation":"Catch-all 500 from register_plugin (POST /claude-code/plugins). HTTPExceptions (the 400s above, name-conflict 409 from UniqueViolationError, DB-not-connected) are re-raised untouched; everything else — unexpected DB failures, missing plugin table, serialization errors — is logged as 'Error registering plugin' and returned as this generic message with the exception string interpolated.","triggerScenarios":"POST /claude-code/plugins when the litellm_claudecodeplugintable does not exist yet (DB migrated by an older LiteLLM before this feature shipped), when the Postgres connection drops mid-insert, or when the manifest built from PluginSpec fails to serialize for the DB write.","commonSituations":"Upgrading LiteLLM to a version that introduced the plugin marketplace while pointing at an existing database that was never re-migrated; transient DB outage during a CI script that registers many plugins; prisma client in a bad state after a DB restart.","solutions":["Read the proxy log: 'Error registering plugin: ...' carries the full traceback (verbose_proxy_logger.exception) — that names the real failure.","If the traceback says the table/relation does not exist, restart the proxy with DATABASE_URL set so Prisma migrations create it, or run the migrations against the database manually.","If it is a connectivity error, verify Postgres is up and credentials valid, then retry the POST once recovered (registration is not idempotent — a 409 on retry means the first attempt actually landed).","Confirm you are not hitting a genuine duplicate-name path via a different code path (direct 409 'already exists' responses are handled separately and will not produce this 500)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    resp = client.post(f\"{base}/claude-code/plugins\", json=payload)\n    resp.raise_for_status()\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 500:\n        # ambiguous: the insert may or may not have committed.\n        existing = client.get(f\"{base}/claude-code/plugins\", headers=hdr)\n        if any(p[\"name\"] == payload[\"name\"] for p in existing.json()[\"plugins\"]):\n            return  # actually registered on the first attempt\n        raise\n    if e.response.status_code == 409:\n        return  # name conflict - treat as registered\n    raise","preventionTips":["Validate the whole payload client-side (name + source rules) before POST to eliminate the 400 paths.","After an ambiguous 500, verify with a follow-up GET instead of blindly re-POSTing (409 vs created).","Keep proxy version and DB migrations in sync so the plugin table always exists."],"tags":["litellm-proxy","claude-code-marketplace","internal-server-error","database","plugin-registration"],"backgroundTag":"internal-server-error","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}