ZhuLinsen/daily_stock_analysis · error · Error

Backend executable not found: ${backendPath}

Error message

Backend executable not found: ${backendPath}

What it means

Raised by PortfolioService.add_corporate_action when the symbol argument cannot be normalized to a canonical stock code. The service calls canonical_stock_code(symbol) via _normalize_symbol_for_storage (portfolio_service.py:1255) and rejects empty/None/unrecognized symbols before writing, because a corporate action row without a valid symbol would poison position replay.

Source

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

function startBackend({ port, envFile, dbPath, logDir, host = null }) {
  const backendPath = resolveBackendPath();
  backendStartError = null;
  const launchStartedAt = Date.now();
  const bindHost = normalizeBackendBindHost(
    normalizeBackendHost(host) || resolveBackendBindHost({ envFile }),
    DESKTOP_BACKEND_DEFAULT_HOST
  );

  const env = buildBackendEnvironment({ envFile, dbPath, logDir, port, host: bindHost });

  const args = buildBackendArgs({ host: bindHost, port });
  let launchMode = '';
  let launchCommand = '';
  let launchCwd = '';

  if (backendPath) {
    if (!fs.existsSync(backendPath)) {
      throw new Error(`Backend executable not found: ${backendPath}`);
    }
    launchMode = 'packaged';
    launchCommand = formatCommand(backendPath, args);
    launchCwd = path.dirname(backendPath);
    backendProcess = spawn(backendPath, args, {
      env,
      cwd: launchCwd,
      stdio: 'pipe',
      windowsHide: true,
    });
  } else {
    const pythonPath = resolvePythonPath();
    const scriptPath = path.join(appRootDev, 'main.py');
    const pythonArgs = ['-X', 'utf8', scriptPath, ...args];
    launchMode = 'development';
    launchCommand = formatCommand(pythonPath, pythonArgs);
    launchCwd = appRootDev;
    backendProcess = spawn(pythonPath, pythonArgs, {

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Pass a recognized symbol format: A-share '600519' or 'SH600519' or '600519.SH', HK 'HK00700' or '00700.HK', US 'AAPL'
  2. If symbol comes from user input, validate/strip it in the caller before calling the service
  3. Check that the symbol string is non-empty after strip(); whitespace-only input is rejected
  4. Log the raw symbol value at the call site to identify which upstream producer sends bad symbols

Example fix

# before
svc.add_corporate_action(account_id=1, symbol="", action_type="cash_dividend", cash_dividend_per_share=0.5, effective_date=d)
# after
svc.add_corporate_action(account_id=1, symbol="600519", action_type="cash_dividend", cash_dividend_per_share=0.5, effective_date=d)
Defensive patterns

Strategy: validation

Validate before calling

from data_provider.base import canonical_stock_code

def valid_corp_action_symbol(symbol):
    return bool((canonical_stock_code(symbol or "") or "").strip())

Type guard

def is_actionable_symbol(symbol: str | None) -> bool:
    """True when add_corporate_action will accept the symbol."""
    return bool(symbol and (canonical_stock_code(symbol) or "").strip())

Try / catch

try:
    svc.add_corporate_action(...)
except ValueError as exc:
    if "symbol is required" in str(exc):
        # surface a field-level error to the form
        raise UserInputError("symbol", str(exc)) from exc
    raise

Prevention

When it happens

Trigger: Calling add_corporate_action(account_id=..., symbol=None), symbol="", symbol=" ", or a symbol string that canonical_stock_code cannot map (e.g. 'NOSUCH', '???'). The check happens inside the portfolio_write_session, after market/currency normalization but before add_corporate_action_in_session.

Common situations: Import scripts or UI forms that submit an empty symbol field; passing a ticker with only whitespace; feeding a raw exchange code that the data_provider canonicalizer does not recognize (e.g. invented tickers or placeholder values during testing).

Related errors


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