ZhuLinsen/daily_stock_analysis · error · Error

当前运行模式不支持自动安装更新。

Error message

当前运行模式不支持自动安装更新。

What it means

Raised by PortfolioService._validate_trade_identity (portfolio_service.py:664) when recording a trade whose client-supplied trade_uid already exists for the same account. It surfaces as PortfolioConflictError (code=conflict) and is the idempotency guard against double-submitting the same external trade reference.

Source

Thrown at apps/dsa-desktop/main.js:1586

    type: 'info',
    buttons: ['稍后', '前往下载'],
    defaultId: 1,
    cancelId: 0,
    title: '发现新版本',
    message: `检测到桌面端新版本 ${state.latestVersion}`,
    detail: `当前版本 ${currentVersion}。新版本将跳转到 GitHub Releases 下载页,不会静默下载或自动安装。`,
    noLink: true,
  });

  if (result.response === 1) {
    await shell.openExternal(sanitizeReleaseUrl(state.releaseUrl));
  }
}

async function installDownloadedUpdate() {
  const updater = getElectronAutoUpdater();
  if (!updater) {
    throw new Error('当前运行模式不支持自动安装更新。');
  }
  if (desktopUpdateState?.status !== UPDATE_STATUS.UPDATE_DOWNLOADED) {
    throw new Error('更新尚未下载完成,无法自动安装。');
  }

  setDesktopUpdateState({
    status: UPDATE_STATUS.INSTALLING,
    updateMode: UPDATE_MODE.AUTO,
    latestVersion: desktopUpdateState?.latestVersion || '',
    releaseUrl: desktopUpdateState?.releaseUrl || RELEASES_PAGE_URL,
    message: '正在重启并安装更新...',
  });
  let backupRoot = null;
  try {
    logLine('[update] stop backend and backup runtime data before install');
    await stopBackend();
    backupRoot = resolveUpdateBackupRoot();
    cleanupUpdateBackupRoot();

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Treat the conflict as success in importers: catch PortfolioConflictError and skip/mark the row as already-imported (idempotent upsert semantics)
  2. Ensure trade_uid is stable and deterministic per external trade (e.g. broker reference or hash of broker+date+symbol+qty+price)
  3. Disable submit buttons / dedupe in-flight requests in the UI
  4. If the trade genuinely should be recorded twice (rare), assign a distinct trade_uid

Example fix

# before
svc.add_trade(account_id=1, symbol="AAPL", ..., trade_uid="broker-42")
# after
try:
    svc.add_trade(account_id=1, symbol="AAPL", ..., trade_uid="broker-42")
except PortfolioConflictError:
    logger.info("trade broker-42 already imported, skipping")
Defensive patterns

Strategy: try-catch

Validate before calling

def already_has_trade(svc, account_id, trade_uid):
    # cheap pre-check when no concurrent writers exist
    existing = svc.query_trades(account_id=account_id, page=1, page_size=1)
    # authoritative check is the service conflict; prefer try/except below
    return False

Type guard

def has_stable_trade_uid(trade_uid: str | None) -> bool:
    """True when the uid is safe to use for idempotency."""
    return bool(trade_uid and trade_uid.strip())

Try / catch

from src.services.portfolio_service import PortfolioConflictError

try:
    svc.add_trade(account_id=a, trade_uid=uid, ...)
except PortfolioConflictError:
    logger.info("trade %s already recorded, skipping", uid)  # idempotent success

Prevention

When it happens

Trigger: add_trade(..., trade_uid='abc123') called twice with the same account_id and trade_uid; a retrying importer (network retry, user double-click) re-sending the same broker record; two threads importing the same statement concurrently. The lookup runs per account, so the same uid under a different account_id is allowed.

Common situations: Broker-statement importers that re-run after a partial failure and resend already-persisted rows; UI double-submit because the button is not disabled; at-least-once message queues delivering the same trade event twice; changing uid generation to a non-deterministic scheme and then reverting.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/b8f267c98f31fa37. Report an issue: GitHub.