langgenius / langgenius/dify

Plugin daemon management list fails entirely when a single installed plugin has an invalid declaration

Open
#41,703 3 comments 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
156k
Forks
24.6k
Avg merge
22h 9m
Merged PRs (30d)
610

Description

### Self Checks

- [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).
- [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
- [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
- [x] I confirm that I am using English to submit this report, otherwise it will be closed.
- [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
- [x] Please do not modify this template :) and fill in all the required fields.

### Dify version

1.17.0 (also present on current `main`)

### Cloud or Self Hosted

Self Hosted (Docker)

### Steps to reproduce

This is the same user-visible failure as #41605, but the root cause is shared by every plugin-daemon **management list** endpoint, not just tools.

1. Install several tool / model / datasource / trigger / agent-strategy plugins so `GET plugin/{tenant}/management/{tools|models|datasources|triggers|agent_strategies}` returns a list.
2. Leave (or mock) **one** list item whose declaration cannot be parsed — for example a tool whose `declaration.tools[].identity` is missing, or whose payload does not match `PluginToolProviderEntity`. The remaining items are valid.
3. Open the Console Tools (or Models / Triggers) page, which calls the corresponding management list API.

Code path on current `main`:

- `BasePluginClient._request_with_plugin_daemon_response` does `PluginDaemonBasicResponse[list[T]].model_validate(...)` atomically (`api/core/plugin/impl/base.py`). Any single invalid element fails the whole response.
- The exception is wrapped as `ValueError("Failed to parse response from plugin daemon to PluginDaemonBasicResponse [list], url: plugin/.../management/tools")`.
- Console `ExternalApi` maps `ValueError` to HTTP **400 `invalid_param`**, so a valid studio page looks like a client error. Same wrapping family as #41675.
- List transformers in `tool.py` / `datasource.py` / `trigger.py` / `agent.py` also do `item["identity"]["provider"] = ...` without a guard. A missing `identity` key raises `KeyError` and is caught by the same `ValueError` wrapper, before Pydantic even runs.

This class of failure has recurred as #41605 (open, tools), and historically #23053 (tools), #27686 / #26272 (datasources), #28921 (triggers), #22397 (agent_strategy), #26927 (plugin list). In #41605 the reporter recovered only by **uninstalling the one bad plugin**; every other plugin on the page stayed unusable until then.

### ✔️ Expected Behavior

A management **list** endpoint should skip an invalid provider, log it, and return the valid remainder so Tools / Models / Triggers / Datasources stay usable.

A **single-provider** GET (`management/tool`, `management/trigger`, …) can still fail hard for that one plugin.

Genuine daemon-down / runtime-not-ready failures should stay on the retryable path from #41675 (503 `plugin_daemon_unavailable`), not `invalid_param`.

### ❌ Actual Behavior

One malformed plugin makes the entire list request fail:

```text
ValueError: Failed to parse response from plugin daemon to PluginDaemonBasicResponse [list],
url: plugin/{tenant_id}/management/tools
```

Console then returns:

```json
{ "code": "invalid_param", "message": "Failed to parse response from plugin daemon to PluginDaemonBasicResponse [list], url: plugin/.../management/tools", "status": 400 }
```

The Tools (or Models / Triggers / Datasources) page cannot load any providers until the operator identifies and removes the one bad plugin.

Related: #41605, #41675, #36244.

Contributor guide

Open the contributing guide

Research direction

Start with BasePluginClient._request_with_plugin_daemon_response in api/core/plugin/impl/base.py, then inspect the list transformers in tool.py, datasource.py, trigger.py, and agent.py. Reproduce the malformed-item case against the management list endpoints and verify that invalid providers are logged and skipped, valid providers remain available, and single-provider or daemon-unavailable failures retain their existing behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.