ZhuLinsen/daily_stock_analysis · error · Error

更新尚未下载完成,无法自动安装。

Error message

更新尚未下载完成,无法自动安装。

What it means

Raised by PortfolioService._validate_trade_identity (portfolio_service.py:666) when a trade's dedup_hash already exists for the account. dedup_hash is the content-based duplicate detector for trades that carry no explicit trade_uid; PortfolioConflictError (code=conflict) tells the caller the identical trade is already stored.

Source

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

    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();

    for (let attempt = 1; attempt <= 3; attempt += 1) {
      try {

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Catch PortfolioConflictError in importers and treat it as already-imported (skip), matching trade_uid semantics
  2. Compute dedup_hash from all identifying fields (symbol, side, date, quantity, price, fee) so genuine duplicates collide but distinct trades never do
  3. Make the import job resumable (track last processed row) so full re-runs are unnecessary
  4. If two truly distinct trades hash the same, fix the hash inputs rather than disabling dedup

Example fix

# before
svc.add_trade(account_id=1, symbol="600519", ...)  # no trade_uid
# after
try:
    svc.add_trade(account_id=1, symbol="600519", ...)
except PortfolioConflictError as exc:
    if "dedup_hash" in str(exc):
        continue  # already imported
Defensive patterns

Strategy: try-catch

Type guard

def dedup_inputs_complete(symbol: str, trade_date, side: str, quantity: float, price: float) -> bool:
    """All identifying fields present, so dedup_hash is well-defined."""
    return bool(symbol and trade_date and side in ("buy", "sell") and quantity > 0 and price > 0)

Try / catch

from src.services.portfolio_service import PortfolioConflictError

try:
    svc.add_trade(account_id=a, ...)
except PortfolioConflictError as exc:
    if "dedup_hash" in str(exc):
        continue  # identical trade already stored; idempotent success
    raise

Prevention

When it happens

Trigger: add_trade(...) without trade_uid called twice with identical field content (same computed dedup_hash under the same account_id); re-running a CSV import after an interruption; resubmitting a form. The scope is per account, and only when dedup_hash is truthy.

Common situations: Import pipelines restarted mid-file replaying earlier rows; double-clicked form submission; at-least-once queues; a bug in the hash computation that collapses distinct trades (e.g. ignoring quantity) making unrelated trades collide.

Related errors


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