langgenius/dify · error · ValueError
PLUGIN_REMOTE_INSTALL_PORT must be a bare port number, got {
Error message
PLUGIN_REMOTE_INSTALL_PORT must be a bare port number, got {v}. A 'host:port' value usually means EXPOSE_PLUGIN_DEBUGGING_PORT was set to a compose publish spec like '127.0.0.1:5003'; bind loopback via a docker-compose.override.yaml instead of overloading this var. What it means
Raised by the before-field-validator _reject_host_port_shaped_plugin_remote_install_port when PLUGIN_REMOTE_INSTALL_PORT is a string containing ':'. The setting must be a bare integer port; the EXPOSE_PLUGIN_DEBUGGING_PORT compose var is overloaded and feeding a publish spec like '127.0.0.1:5003' here would otherwise crash Pydantic int parsing and crashloop the api container (issue #39323).
Source
Thrown at api/configs/feature/__init__.py:302
NEW_USER_DEFAULT_PLUGIN_IDS: str = Field(
description="Comma-separated marketplace plugin IDs whose latest versions are installed for new users",
default="",
)
@field_validator("PLUGIN_REMOTE_INSTALL_PORT", mode="before")
@classmethod
def _reject_host_port_shaped_plugin_remote_install_port(cls, v):
"""Reject ``host:port``-shaped values with an actionable hint.
``EXPOSE_PLUGIN_DEBUGGING_PORT`` is overloaded: it feeds both the
plugin_daemon ``ports:`` mapping (where ``127.0.0.1:5003`` is valid
compose syntax) and this integer app setting advertised in the console.
Without this guard a loopback bind spec crashloops the api container
with an opaque ``int_parsing`` traceback. See issue #39323.
"""
if isinstance(v, str) and ":" in v.strip():
raise ValueError(
"PLUGIN_REMOTE_INSTALL_PORT must be a bare port number, got "
f"{v!r}. A 'host:port' value usually means "
"EXPOSE_PLUGIN_DEBUGGING_PORT was set to a compose publish spec "
"like '127.0.0.1:5003'; bind loopback via a "
"docker-compose.override.yaml instead of overloading this var."
)
return v
@property
def NEW_USER_DEFAULT_PLUGIN_ID_LIST(self) -> list[str]:
return [item.strip() for item in self.NEW_USER_DEFAULT_PLUGIN_IDS.split(",") if item.strip()]
NEW_USER_DEFAULT_MODELS: str = Field(
description=("Comma-separated default models for new users in 'model_type:provider:model' format"),
default="",
)
@propertyView on GitHub (pinned to ef8544b173)
Solutions
- Set PLUGIN_REMOTE_INSTALL_PORT to a bare integer, e.g. '5003'.
- Keep the loopback bind in docker-compose 'ports:' (or an override file) instead of the env var.
- Decouple EXPOSE_PLUGIN_DEBUGGING_PORT so it only feeds the compose mapping, not the app setting.
Example fix
// before PLUGIN_REMOTE_INSTALL_PORT=127.0.0.1:5003 // after PLUGIN_REMOTE_INSTALL_PORT=5003
Defensive patterns
Strategy: validation
Validate before calling
def is_bare_port(v) -> bool:
if isinstance(v, int):
return 0 <= v <= 65535
if isinstance(v, str):
s = v.strip()
return ':' not in s and s.isdigit() and 0 <= int(s) <= 65535
return False Prevention
- Keep EXPOSE_PLUGIN_DEBUGGING_PORT (compose) and PLUGIN_REMOTE_INSTALL_PORT (app) as separate values.
- Document the loopback bind in a docker-compose.override.yaml.
- Add a CI lint that rejects ':' in PLUGIN_REMOTE_INSTALL_PORT.
When it happens
Trigger: Setting PLUGIN_REMOTE_INSTALL_PORT (or EXPOSE_PLUGIN_DEBUGGING_PORT if it is wired to the same value) to '127.0.0.1:5003' or any 'host:port' string.
Common situations: Operator copies the compose 'ports:' publish value into the app-level env var, or aliases EXPOSE_PLUGIN_DEBUGGING_PORT to a bind spec.
Related errors
- KNOWLEDGE_FS_BASE_URL must be an absolute HTTP(S) URL
- KNOWLEDGE_FS_BASE_URL must include a valid port
- KNOWLEDGE_FS_BASE_URL must not include credentials, query, o
- KNOWLEDGE_FS_BASE_URL and KNOWLEDGE_FS_JWT_SECRET must be co
- KnowledgeFS connection settings are required when the integr
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/ac88ad3c095c9ce9.
Report an issue: GitHub.