Documentsdify
Release Breaking Changes
Release Breaking Changes
Type
Topic
Status
Published
Created
Jul 16, 2026
Updated
Jul 16, 2026
Created by
Dosu Bot
Updated by
Dosu Bot

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 require additional manual steps.


model_type Enum Rename — 1.14.x#

Affected versions: Any instance upgrading to 1.14.0 or later with pre-existing model provider records.

What changed#

Dify 1.14.x renamed model_type column values in the dify PostgreSQL database without running a data migration against existing rows :

Old valueNew value
text-generationllm
embeddingstext-embedding
rerankingrerank

The code-level rename is tracked in PR #34488 and the bug was closed in PR #36520 .

Symptoms#

  • UI shows "Credentials unavailable" on all pre-configured model providers
  • HTTP 400 "Credential with id … not found" in browser console
  • Model deletions appear to succeed but the record reappears on refresh
  • Inference still works — only management operations (view, edit, delete) are broken

Fix#

Back up the affected tables, then run against the dify database :

UPDATE provider_models SET model_type = 'llm' WHERE model_type = 'text-generation';
UPDATE provider_models SET model_type = 'text-embedding' WHERE model_type = 'embeddings';
UPDATE provider_models SET model_type = 'rerank' WHERE model_type = 'reranking';

UPDATE provider_model_credentials SET model_type = 'llm' WHERE model_type = 'text-generation';
UPDATE provider_model_credentials SET model_type = 'text-embedding' WHERE model_type = 'embeddings';
UPDATE provider_model_credentials SET model_type = 'rerank' WHERE model_type = 'reranking';

UPDATE tenant_default_models SET model_type = 'llm' WHERE model_type = 'text-generation';
UPDATE tenant_default_models SET model_type = 'text-embedding' WHERE model_type = 'embeddings';
UPDATE tenant_default_models SET model_type = 'rerank' WHERE model_type = 'reranking';

UPDATE provider_model_settings SET model_type = 'llm' WHERE model_type = 'text-generation';
UPDATE provider_model_settings SET model_type = 'text-embedding' WHERE model_type = 'embeddings';
UPDATE provider_model_settings SET model_type = 'rerank' WHERE model_type = 'reranking';

UPDATE load_balancing_model_configs SET model_type = 'llm' WHERE model_type = 'text-generation';
UPDATE load_balancing_model_configs SET model_type = 'text-embedding' WHERE model_type = 'embeddings';
UPDATE load_balancing_model_configs SET model_type = 'rerank' WHERE model_type = 'reranking';

tenant_default_models edge case: If the UPDATE throws SQLSTATE 23505 (duplicate key on the (tenant_id, model_type) unique constraint), the new value already exists for that tenant. 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.

What changed#

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 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, and more — 14 ranges total)
  • 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_proxy container logs show: TCP_DENIED/403 for the blocked destination
  • ToolSSRFError: Access to '<url>' was blocked by SSRF protection in stack traces

Fix#

Add exceptions via .env and restart the proxy :

VariableAllows
SSRF_PROXY_ALLOW_PRIVATE_DOMAINSNamed hosts/domains that resolve to private IPs
SSRF_PROXY_ALLOW_PRIVATE_IPSSpecific 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

The 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#

VersionIssueReference
1.13.x → 1.14.xDuplicate plugin_unique_identifier in dify_plugin.plugins causes daemon restart loop (SQLSTATE 23505)Issue #38276
1.15.0+Stale plugin version directories on disk cause record not found in daemon logs; run flask backfill-plugin-auto-upgradeIssue #38268
1.15.0DB_TYPE env var now required; add DB_TYPE=postgresql

Key References#

ResourceNotes
Issue #36129Primary thread for model_type enum mismatch, with full SQL fix
Discussion #38100SSRF 403 after 1.10.x → 1.15.0 upgrade, with resolution
squid.conf.templateFull Squid ACL rules
api/core/helper/ssrf_proxy.pyAPI-layer SSRF detection and ToolSSRFError
Plugin Database Integrity KBAll four plugin DB failure patterns with diagnostics
Release Breaking Changes | Dosu