langgenius / langgenius/dify

[Feature] Marketplace should handle plugin ↔ Dify version compatibility (`minimum_dify_version` is currently a no-op)

Open
#41,048 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
156k
Forks
24.6k
Avg merge
20h 50m
Merged PRs (30d)
586

Description

# [Feature] Marketplace should handle plugin ↔ Dify version compatibility (`minimum_dify_version` is currently a no-op)

> Target repo: `langgenius/dify` (behavior also spans the hosted Marketplace API and `langgenius/dify-plugin-daemon`)

## Self Checks

- [x] I have searched for existing issues, including closed ones.
- [x] I confirm that I am using English to submit this report.
- [x] Please do not modify this template :) and fill in all the required fields.

## 1. Is this request related to a challenge you're experiencing?

Yes. When installing a plugin (from Marketplace, GitHub, or local package) onto a self-hosted Dify, a plugin that requires a **newer** Dify version than the one running installs **without any warning or block**. The incompatibility only surfaces later at runtime — a node/tool fails (`PluginNotFoundError`, `PluginInvokeError`, or silent misbehavior) — which is hard to trace back to a version mismatch.

The plugin manifest already carries `meta.minimum_dify_version` for exactly this purpose, but today it is **write-only**: it is declared and format-validated, yet **no code path ever compares it against the running Dify version.**

### Evidence (paths as of 1.14.x; symbols are stable)

**a) The field is defined and only *format*-validated — never compared** — `api/core/plugin/entities/plugin.py`:
```python
class Meta(BaseModel):
minimum_dify_version: str | None = Field(default=None)

@field_validator("minimum_dify_version")
@classmethod
def validate_minimum_dify_version(cls, v: str | None) -> str | None:
if v is None:
return v
try:
Version(v) # only checks it parses as a version
return v
except InvalidVersion as e:
raise ValueError(f"Invalid version format: {v}") from e
```
A repo-wide search for `minimum_dify_version` returns only this definition + unit tests. No business logic reads it.

**b) Install/upgrade paths do not gate on it** — `api/services/plugin/plugin_service.py`: `install_from_local_pkg`, `install_from_github`, and `install_from_marketplace_pkg` only check marketplace-only permission and signature/source verification. Neither reads `declaration.meta.minimum_dify_version` nor compares the Dify version.

**c) The plugin daemon writes the field at scaffold time but never reads it at install time** — `cmd/commandline/plugin/init.go` writes it from `--min-dify-version` into `PluginMeta.MinimumDifyVersion` (`pkg/entities/plugin_entities/plugin_declaration.go`, no `validate` tag), but `internal/tasks/install_plugin.go` has no version-compatibility logic. The only real version comparison in the daemon (`internal/core/local_runtime/patch.go`) compares the **plugin SDK version** against hardcoded thresholds to patch old SDKs — unrelated to the host Dify version.

**d) The Marketplace already knows the caller's Dify version but does nothing version-aware with it** — `api/core/helper/marketplace.py` forwards the running version as a header on every call and displays whatever the server returns:
```python
headers={"X-Dify-Version": dify_config.project.version}
```
The client-side Marketplace response entity (`api/core/plugin/entities/marketplace.py`) exposes `latest_version` but has **no** `minimum_dify_version`, so the client couldn't filter or warn even if it wanted to.

## 2. Describe the feature you'd like to see

**The compatibility guarantee should live on the Marketplace/server side, not depend on clients upgrading Dify.** The server already receives `X-Dify-Version` on every request — it should use it:

1. **Version-aware Marketplace responses (primary ask).** Given the caller's `X-Dify-Version`, the Marketplace API should resolve to the **latest plugin version compatible with that Dify version** (not merely the global `latest_version`), and mark/withhold versions whose `minimum_dify_version` exceeds the caller's version. A self-hosted instance pinned to, say, 1.14.2 should be offered a working plugin build for 1.14.2 — never handed a build that silently can't run.
2. **Expose `minimum_dify_version` (and ideally a tested-compatibility range) in the Marketplace payload**, so any client can display a compatibility badge and disable install for incompatible builds.
3. **Install-time safety net (secondary).** As a backstop for GitHub/local-package installs that bypass the Marketplace, compare `declaration.meta.minimum_dify_version` with `dify_config.project.version` before finalizing install; block by default with an explicit message (e.g. `Plugin X requires Dify >= 1.15.0, current is 1.14.2`) plus an "install anyway" override.

Why server-side first: **self-hosted users realistically cannot upgrade Dify on demand** — upgrades carry data-migration and infra risk and are often pinned for stability. Telling them "upgrade Dify to use this plugin" is not an acceptable resolution. Serving a version-appropriate plugin build (or clearly saying none exists) keeps a pinned deployment working, and only needs the version signal the client already sends.

## 3. How will this feature improve your workflow/experience

- Turns a class of hard-to-diagnose runtime failures into an up-front, actionable state (compatible build served, or a clear "not available for your version").
- Removes the current "guess the right version pairing" burden users already carry (see linked threads).
- Makes the existing `minimum_dify_version` field meaningful for plugin authors instead of a silent no-op.
- Respects pinned self-hosted deployments instead of forcing Dify upgrades.

## 4. Additional context

Related symptom reports that server-side version awareness would have prevented:
- `langgenius/dify` #34275 — plugins stop working after a cross-version Dify upgrade.
- `langgenius/dify-plugin-daemon` #762 — local plugin then Marketplace update leads to *plugin not found*.
- `langgenius/dify-plugin-daemon` #696 — version pairing breaks plugin install after a daemon upgrade.
- discussion #34269 — users manually guessing which daemon/plugin version pairs with which Dify version.

Note on scope: the primary fix lives in the **hosted Marketplace API**, which is not in the open-source tree — so external contributors can't fully implement it, hence this is filed as an issue rather than a PR.

- [ ] I'm willing to help contribute the open-source portion (install-time backstop + console warning) if maintainers agree on the desired UX.

Contributor guide

Open the contributing guide

Research direction

Start by reading api/services/plugin/plugin_service.py and the manifest entities in api/core/plugin/entities/plugin.py, then inspect internal/tasks/install_plugin.go and the Marketplace request handling described in api/core/helper/marketplace.py. Verify how existing version validation and installation paths work before defining the compatibility behavior. Done should include an explicit response or install-time outcome for incompatible versions, but the primary Marketplace API is outside this repository.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, python
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.