Release Breaking Changes#
Catalog of critical backward-incompatible changes in Dify that require operator action during upgrades. Standard flask upgrade-db / docker compose up is not sufficient for these; they each require additional manual steps.
Upgrade checklist (any major version): (1)
flask upgrade-db, (2)flask backfill-plugin-auto-upgrade, (3) verify plugin daemon image tag matches the Dify release, (4) remove stale plugin version directories fromPLUGIN_INSTALLED_PATH.
model_type Enum Rename β 1.14.x#
Affected versions: Any instance upgrading to 1.14.0 or later with pre-existing model provider records.
Dify 1.14.x renamed model_type column values in the PostgreSQL dify database without running a data migration against existing rows :
| Old value | New value |
|---|---|
text-generation | llm |
embeddings | text-embedding |
reranking | rerank |
The rename mapping is codified in legacy_model_type_migration.py. The application-level code change is tracked in PR #34488 and the database fix landed in PR #36520.
Symptoms :
- UI shows "Credentials unavailable" on all pre-configured model providers
- Browser console shows
HTTP 400 "Credential with id β¦ not found" - Model deletions appear to succeed but records reappear on refresh
- Inference still works β only management operations (view, edit, delete) are broken
Fix#
Versions with Alembic migration 2026_08_27_1200-5578e028b2f2 and later (PR #41326):
flask db upgrade applies the fix automatically. The migration service canonicalizes legacy values across all five affected tables (provider_models, provider_model_credentials, tenant_default_models, provider_model_settings, load_balancing_model_configs), resolves duplicate-key collisions deterministically (newest row wins), and rotates the provider cache namespace to v2 to invalidate stale cached credentials.
The CLI command for an online migration (before or after DB upgrade) is available via api/commands/data_migrate.py:
# Dry-run first (default)
docker compose exec api flask data-migrate legacy-model-types
# Apply (requires --apply flag)
docker compose exec api flask data-migrate legacy-model-types --apply
Older versions or manual fix:
Back up affected tables, then run against the dify database :
-- Repeat for each of: provider_models, provider_model_credentials,
-- tenant_default_models, provider_model_settings, load_balancing_model_configs
UPDATE <table> SET model_type = 'llm' WHERE model_type = 'text-generation';
UPDATE <table> SET model_type = 'text-embedding' WHERE model_type = 'embeddings';
UPDATE <table> SET model_type = 'rerank' WHERE model_type = 'reranking';
tenant_default_models edge case: If the UPDATE throws SQLSTATE 23505 (duplicate key on (tenant_id, model_type)), delete the stale legacy-valued row first:
DELETE FROM tenant_default_models
WHERE tenant_id = '<id>' AND model_type IN ('text-generation','embeddings','reranking');
After the SQL fix, uninstall and reinstall affected model plugins to ensure plugin state is consistent.
SSRF Proxy Deny-by-Default β 1.15.0#
Affected versions: Upgrades from any version < 1.15.0 where workflows or HTTP-request nodes call non-marketplace URLs (including internal/private endpoints).
As of 1.15.0, the Squid SSRF proxy enforces a deny-by-default policy. Previously, outbound HTTP requests from workflow nodes passed through with far fewer restrictions. The proxy now blocks all RFC-1918/private IP ranges and all destinations except .marketplace.dify.ai by default.
See docker/ssrf_proxy/squid.conf.template for the full ACL list.
Symptoms :
- Workflow HTTP-request nodes return
403 Forbidden - Worker logs show:
Request to URL <url> failed on attempt 1: 403 Forbidden ssrf_proxycontainer logs show:TCP_DENIED/403for blocked destinationsToolSSRFError: Access to '<url>' was blocked by SSRF protectionin stack traces
Fix#
Add allowlist exceptions via .env and restart the proxy :
| Variable | Allows |
|---|---|
SSRF_PROXY_ALLOW_PRIVATE_DOMAINS | Named hosts/domains that resolve to private IPs |
SSRF_PROXY_ALLOW_PRIVATE_IPS | Specific private IPs or CIDR ranges |
Example .env additions:
SSRF_PROXY_ALLOW_PRIVATE_DOMAINS=internal.mycompany.com,ollama
SSRF_PROXY_ALLOW_PRIVATE_IPS=10.10.5.42,192.168.1.0/24
Then restart:
docker compose restart ssrf_proxy
# or for full config regeneration:
docker compose down && docker compose up -d
docker/ssrf_proxy/docker-entrypoint.sh reads these variables at startup and generates Squid ACL fragments into /etc/squid/dify_allow_private.conf, which is evaluated before the deny rules.
Other Known Upgrade Issues#
| Version | Issue | Fix | Reference |
|---|---|---|---|
| 1.13.x β 1.14.x | Duplicate plugin_unique_identifier in dify_plugin.plugins causes daemon restart loop (SQLSTATE 23505) | Deduplicate rows in dify_plugin.plugins, then restart daemon | Issue #38276 |
| 1.15.0+ | Stale plugin version directories on disk cause record not found in daemon logs | Run flask backfill-plugin-auto-upgrade; remove stale dirs from PLUGIN_INSTALLED_PATH | Issue #38268 |
| 1.15.0 | DB_TYPE env var now required | Add DB_TYPE=postgresql to .env |
Plugin daemon version lockstep: The plugin daemon must be kept in version lockstep with the Dify API. Protocol mismatches cause complete communication failure. Known pairings :
| Dify API | Plugin Daemon |
|---|---|
| 1.13.x | 0.5.x |
| 1.14.x | 0.6.x |
| 1.15.0 | 0.6.10-local |
The upgrade checklist is repeated above in the intro block for quick reference. See the Plugin Daemon Architecture KB for full details on daemon version synchronization and troubleshooting.
Key References#
| Resource | Notes |
|---|---|
| Issue #36129 | Primary thread for model_type enum mismatch, with full SQL fix |
| Discussion #38100 | SSRF 403 after 1.10.x β 1.15.0 upgrade, with resolution |
api/services/legacy_model_type_migration.py | LegacyModelTypeMigrationService β online migration logic for all five tables |
api/commands/data_migrate.py | flask data-migrate legacy-model-types CLI command |
squid.conf.template | Full Squid ACL rules (deny-by-default list) |
api/core/helper/ssrf_proxy.py | API-layer SSRF detection and ToolSSRFError |
| Plugin Database Integrity KB | All four plugin DB failure patterns with diagnostic queries and SQL scripts |
| Issue #41294 | Post-1.17.0 upgrade model usability report |