Plugin Marketplace Connectivity#
Dify's plugin system requires outbound HTTPS access to marketplace.dify.ai for browsing, downloading, and installing plugins. In firewalled, air-gapped, or proxy-intercepting environments this connection fails, producing errors ranging from DNS resolution failures to MaxRetriesExceededError. The marketplace is optional — core Dify functionality is unaffected when it is unreachable, but no marketplace-sourced plugins can be installed or updated without it.
Edition Differences: Detail Pages#
COMMUNITY and ENTERPRISE editions open plugin and template detail pages on the official Marketplace (marketplace.dify.ai) in a new browser tab. CLOUD edition continues to display details in-app within modal dialogs.
For COMMUNITY and ENTERPRISE users, this means two types of connectivity are required:
- Backend connectivity (server →
marketplace.dify.ai): The Dify API container needs outbound HTTPS to browse, search, and install plugins. - Browser connectivity (user's browser →
marketplace.dify.ai): The user's browser must also reach the Marketplace site to view detail pages.
If backend connectivity works but the browser cannot reach marketplace.dify.ai, users will be able to browse the marketplace and install plugins, but clicking a plugin or template card to view details will fail. Browser-level blocks are typically caused by corporate firewalls, DNS filtering, or proxy policies that differ from server-side network rules.
Architecture#
Plugin installation flows through two layers:
-
api/core/helper/marketplace.py— orchestrates calls tomarketplace.dify.ai. Key functions:download_plugin_pkg()— fetches the.difypkgbinary viaapi/v1/plugins/download-urlbatch_fetch_plugin_manifests()— POSTs toapi/v1/plugins/batchto resolve plugin metadatafetch_global_plugin_manifest()— GETsapi/v1/dist/plugins/manifest.jsonand caches results in Redis
All calls use a hard-coded 30-second timeout (
MARKETPLACE_TIMEOUT = 30) and rawhttpx(no SSRF proxy). -
api/core/helper/download.py—download_with_size_limit()delegates the actual byte-fetch toremote_fetcher.make_request(), raisingValueErroron 404 or size violations.
The marketplace base URL is controlled by two env vars in MarketplaceConfig :
| Env var | Default | Effect |
|---|---|---|
MARKETPLACE_ENABLED | True | Toggle marketplace UI and API access |
MARKETPLACE_API_URL | https://marketplace.dify.ai | Override the marketplace endpoint |
Error Types and Where They Surface#
| Error | Root cause | Location |
|---|---|---|
httpx.ConnectError: Temporary failure in name resolution | DNS cannot resolve marketplace.dify.ai | marketplace.py → batch_fetch_plugin_manifests |
httpx.ConnectError / httpx.TimeoutException | Firewall drops the connection | Same call path |
MaxRetriesExceededError | SSRF proxy retry loop exhausted (for requests routed through Squid) | api/core/helper/ssrf_proxy.py |
ValueError: file not found | Marketplace returned 404 for the download URL | download.py |
MaxRetriesExceededError and marketplace downloads: Calls in marketplace.py use raw httpx — not the SSRF proxy — so MaxRetriesExceededError is not raised on marketplace download failures. That error comes from ssrf_proxy.make_request() when other outbound requests (HTTP Request nodes, tool calls) exhaust their Squid-based retry budget. DNS/connection failures from the marketplace propagate as httpx.ConnectError and are swallowed by broad except Exception handlers in plugin_migration.py, which log the failure and mark the plugin as not-found.
Diagnosing Connectivity#
Verify reachability from inside the api container:
docker compose exec api curl -v https://marketplace.dify.ai
Common failure signatures in api container logs:
WARNING ... fetch_latest_plugin_version ... [Errno -3] Temporary failure in name resolution— DNS blockedERROR ... failed to fetch latest plugin versionfollowed by anhttpx.ConnectErrorstack trace — network-level blockTCP_DENIED/403inssrf_proxycontainer output — Squid ACL blocking the request
For COMMUNITY and ENTERPRISE editions: If users can browse the marketplace but cannot view detail pages (clicking a card does nothing or opens a blank tab), the issue is likely browser-side connectivity. Test by opening https://marketplace.dify.ai directly in the user's browser. If that fails, check DNS, firewalls, or proxy settings on the client machine — not the Dify server.
Workarounds for Restricted Environments#
1. Disable the marketplace entirely
Set MARKETPLACE_ENABLED=false in .env to prevent the API from attempting marketplace calls at startup or during plugin sync. Plugins already installed will continue to work.
2. Corporate proxy / Zscaler / SSL inspection
If the connection fails with a TLS certificate error (Zscaler acts as a MITM proxy), inject your company's root CA into the api, web, and plugin_daemon containers. Alternatively set HTTP_PROXY / HTTPS_PROXY on those services in docker-compose.yaml so the container routes through the corporate proxy.
3. Manual .difypkg install (air-gapped)
Download .difypkg files from the Dify Marketplace web UI, transfer them to the isolated host, and upload via Plugins → Upload Plugin in the Dify console. No marketplace connectivity is required for this path.
4. Plugin packages with embedded uv.lock (air-gapped edge case)
Plugins v0.0.53+ of openai-api-compatible ship a uv.lock that hardcodes files.pythonhosted.org URLs, bypassing any private PyPI proxy. Community-tested workaround :
- Set
ENFORCE_LANGGENIUS_PLUGIN_SIGNATURES=falseandFORCE_VERIFYING_SIGNATURE=falsein theplugin_daemonenv. - Strip the lock file:
zip -d plugin.difypkg uv.lock - Upload the modified package; then
execinto theplugin_daemoncontainer and runuv syncinside the unpacked plugin directory, pointing at your internal PyPI proxy.
A proper fix (bundling complete offline packages) is tracked in issue #41849.
A community repackaging tool is also available: dify-plugin-repackaging.
Key Files#
| File | Purpose |
|---|---|
api/core/helper/marketplace.py | All marketplace API calls; configure MARKETPLACE_API_URL here |
api/configs/feature/__init__.py (lines 344–357) | MARKETPLACE_ENABLED and MARKETPLACE_API_URL env var defaults |
api/core/helper/download.py | download_with_size_limit() used for .difypkg fetches |
api/core/helper/ssrf_proxy.py (lines 44–47) | MaxRetriesExceededError definition |
api/services/plugin/plugin_migration.py | Marketplace error handling during plugin sync/migration |