ZhuLinsen/daily_stock_analysis · error · FutuPortfolioError
FUTU_OPEND_PORT 不是有效端口: {raw_port!r}
Error message
FUTU_OPEND_PORT 不是有效端口: {raw_port!r} What it means
FutuPortfolioError raised in _connection_settings (src/brokers/futu/portfolio.py:123) when the FUTU_OPEND_PORT environment variable is set but int() cannot parse it (e.g. 'abc', '11 111', ''). Empty/unset falls back to the default 11111; only a set-but-non-numeric value raises.
Source
Thrown at src/brokers/futu/portfolio.py:123
"""Close an SDK context without masking the primary operation result."""
if context is None:
return
try:
context.close()
except Exception: # pragma: no cover - closing is best effort
logger.debug("关闭 Futu OpenD 连接失败", exc_info=True)
def _connection_settings() -> tuple[str, int]:
"""Return the validated IPv4 OpenD host and port from environment settings."""
host = (os.getenv("FUTU_OPEND_HOST") or "127.0.0.1").strip()
raw_port = (os.getenv("FUTU_OPEND_PORT") or "11111").strip()
try:
port = int(raw_port)
except ValueError as exc:
raise FutuPortfolioError(f"FUTU_OPEND_PORT 不是有效端口: {raw_port!r}") from exc
if not host or not 1 <= port <= 65535:
raise FutuPortfolioError(f"Futu OpenD 地址无效: {host!r}:{port}")
address_text = host[1:-1] if host.startswith("[") and host.endswith("]") else host
try:
address = ipaddress.ip_address(address_text)
except ValueError:
address = None
if address is not None and address.version != 4:
raise FutuPortfolioError(
"futu-api==10.8.6808 的网络层仅支持 IPv4;"
f"FUTU_OPEND_HOST 当前为 {host!r},请改用 IPv4 地址或可解析到 IPv4 的主机名。"
)
return host, port
def _configured_account_id() -> Optional[int]:
"""Return the optional configured real account ID."""View on GitHub (pinned to 5159bd72e8)
Solutions
- Set FUTU_OPEND_PORT to a plain integer between 1 and 65535 (default OpenD port is 11111), or unset it to use the default.
- Check for whitespace/quotes/CRLF in the .env value; the code strips spaces but not other artifacts — retype the line cleanly.
- If set in docker/Actions, print the resolved value at startup (e.g. repr) to catch injection artifacts.
Example fix
# before (.env) FUTU_OPEND_PORT="11111 " # or 11O11 with letter O # after (.env) FUTU_OPEND_PORT=11111
Defensive patterns
Strategy: validation
Validate before calling
def valid_opend_port(raw: str | None) -> bool:
if raw is None or not raw.strip():
return True # default 11111 used
try:
return 1 <= int(raw.strip()) <= 65535
except ValueError:
return False Prevention
- Keep FUTU_OPEND_PORT as a bare integer (usually 11111) in .env and CI variables.
- Unset the variable rather than setting placeholder values.
- Validate env-derived ints at process start with a fail-fast config check.
When it happens
Trigger: Setting FUTU_OPEND_PORT to a non-integer string in .env, docker-compose, or GitHub Actions secrets; copy-paste artifacts like quotes, spaces, a port range '11111-11112', or a URL fragment; a stray newline or BOM in a .env file.
Common situations: Typo in .env ('FUTU_OPEND_PORT=111l1'); accidentally pasting the full host:port into the port var; Windows line endings or invisible characters in env files loaded via dotenv.
Related errors
- Futu OpenD 地址无效: {host!r}:{port}
- FUTU_ACC_ID 必须是正整数账户 ID
- 不支持的 FUTU_SECURITY_FIRM: {name}
- TUSHARE_HTTP_URL 必须以 http:// 或 https:// 开头,当前值为 {url!r}
- 加载 Futu OpenAPI SDK 失败: {exc}
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/868b5f1c9d45d39b.
Report an issue: GitHub.