Plugin daemon management list fails entirely when a single installed plugin has an invalid declaration
- 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
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