Self Checks
Dify version
1.13.2 (also confirmed on latest main)
Cloud or Self Hosted
Self Hosted (Kubernetes)
Steps to reproduce
- Install several plugins from the Marketplace (e.g. openai, anthropic, deepseek, etc.)
- Delete or recreate the PVC backing
/app/storage/plugin_packages/ on the plugin-daemon pod (simulating storage loss, node migration, or PVC reprovisioning)
- Restart the plugin-daemon pod
- Wait for the periodic plugin auto-upgrade check to run (
process_tenant_plugin_autoupgrade_check_task), or trigger a manual upgrade from the UI
✔️ Expected Behavior
When the .difypkg file is missing from disk, the upgrade flow should detect this and re-download the package from the Marketplace, even if the DB/Redis declaration still exists.
❌ Actual Behavior
All plugins that had their package files removed show the error:
failed to move plugin to installed bucket: failed to get package file when trying to install plugin to local
open /app/storage/plugin_packages/langgenius/openai:0.3.4@3345b59...: no such file or directory
This affects every plugin whose .difypkg file was lost. In our case, 30+ plugins were affected simultaneously after a PVC recreation.
Root Cause
There are two affected code paths:
1. UI manual upgrade — PluginService.upgrade_plugin_with_marketplace() in api/services/plugin/plugin_service.py:
try:
manager.fetch_plugin_manifest(tenant_id, new_plugin_unique_identifier)
# already downloaded, skip
marketplace.record_install_plugin_event(new_plugin_unique_identifier)
except Exception:
pkg = download_plugin_pkg(new_plugin_unique_identifier)
...
fetch_plugin_manifest only queries the daemon DB for a PluginDeclaration record — it does not verify the .difypkg file on disk. When the file is missing but the DB record remains, the try block succeeds, the download is skipped, and the upgrade fails.
2. Auto-upgrade celery task — process_tenant_plugin_autoupgrade_check_task() in api/tasks/process_tenant_plugin_autoupgrade_check_task.py:
This task calls manager.upgrade_plugin() directly without any file existence check at all. It never verifies that the package file is present before asking the daemon to perform the upgrade.
Proposed Fix
Add decode_plugin_from_identifier() calls to verify the package file exists on disk before proceeding with upgrades:
Path 1 — plugin_service.py: Add a decode_plugin_from_identifier call after fetch_plugin_manifest:
try:
manager.fetch_plugin_manifest(tenant_id, new_plugin_unique_identifier)
manager.decode_plugin_from_identifier(tenant_id, new_plugin_unique_identifier)
marketplace.record_install_plugin_event(new_plugin_unique_identifier)
except Exception:
pkg = download_plugin_pkg(new_plugin_unique_identifier)
...
Path 2 — auto-upgrade task: Add decode check + download fallback before upgrade_plugin():
try:
manager.decode_plugin_from_identifier(tenant_id, new_unique_identifier)
except Exception:
pkg = download_plugin_pkg(new_unique_identifier)
manager.upload_pkg(tenant_id, pkg, verify_signature=False)
manager.upgrade_plugin(...)
decode_plugin_from_identifier calls the daemon's GetPackage() which reads the actual file, so it raises an exception if the file is missing, triggering the re-download.
Self Checks
Dify version
1.13.2 (also confirmed on latest
main)Cloud or Self Hosted
Self Hosted (Kubernetes)
Steps to reproduce
/app/storage/plugin_packages/on the plugin-daemon pod (simulating storage loss, node migration, or PVC reprovisioning)process_tenant_plugin_autoupgrade_check_task), or trigger a manual upgrade from the UI✔️ Expected Behavior
When the
.difypkgfile is missing from disk, the upgrade flow should detect this and re-download the package from the Marketplace, even if the DB/Redis declaration still exists.❌ Actual Behavior
All plugins that had their package files removed show the error:
This affects every plugin whose
.difypkgfile was lost. In our case, 30+ plugins were affected simultaneously after a PVC recreation.Root Cause
There are two affected code paths:
1. UI manual upgrade —
PluginService.upgrade_plugin_with_marketplace()inapi/services/plugin/plugin_service.py:fetch_plugin_manifestonly queries the daemon DB for aPluginDeclarationrecord — it does not verify the.difypkgfile on disk. When the file is missing but the DB record remains, the try block succeeds, the download is skipped, and the upgrade fails.2. Auto-upgrade celery task —
process_tenant_plugin_autoupgrade_check_task()inapi/tasks/process_tenant_plugin_autoupgrade_check_task.py:This task calls
manager.upgrade_plugin()directly without any file existence check at all. It never verifies that the package file is present before asking the daemon to perform the upgrade.Proposed Fix
Add
decode_plugin_from_identifier()calls to verify the package file exists on disk before proceeding with upgrades:Path 1 — plugin_service.py: Add a
decode_plugin_from_identifiercall afterfetch_plugin_manifest:Path 2 — auto-upgrade task: Add decode check + download fallback before
upgrade_plugin():decode_plugin_from_identifiercalls the daemon'sGetPackage()which reads the actual file, so it raises an exception if the file is missing, triggering the re-download.