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
- Treat the conflict as success in importers: catch PortfolioConflictError and skip/mark the row as already-imported (idempotent upsert semantics)
- Ensure trade_uid is stable and deterministic per external trade (e.g. broker reference or hash of broker+date+symbol+qty+price)
- Disable submit buttons / dedupe in-flight requests in the UI
- 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
- Derive trade_uid deterministically from the broker reference
- Treat code=conflict as success in importers (skip and continue)
- Disable double-submit in UIs; dedupe in-flight requests
- Keep uids unique per account but stable across retries
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.