ZhuLinsen/daily_stock_analysis · error · FileNotFoundError

generated Web index not found: {WEB_INDEX_PATH}

Error message

generated Web index not found: {WEB_INDEX_PATH}

What it means

_sync_static_index copies apps/dsa-web/public/stocks.index.json (WEB_INDEX_PATH) into the static assets directory and refuses to continue if the source file does not exist. That index is itself a build artifact produced by this script's earlier generation phase (from data/stock_list_*.csv), so its absence means the generation step was skipped or failed before the sync step.

Source

Thrown at scripts/refresh_stock_index.py:51

def _has_tushare_token() -> bool:
    env_path = REPO_ROOT / ".env"
    try:
        from dotenv import load_dotenv  # type: ignore
    except ImportError:
        if env_path.is_file():
            for line in env_path.read_text(encoding="utf-8", errors="ignore").splitlines():
                key, sep, value = line.partition("=")
                if sep and key.strip() == "TUSHARE_TOKEN" and value.strip().strip("'\""):
                    return True
        return bool(os.getenv("TUSHARE_TOKEN", "").strip())

    load_dotenv(env_path)
    return bool(os.getenv("TUSHARE_TOKEN", "").strip())


def _sync_static_index() -> None:
    if not WEB_INDEX_PATH.is_file():
        raise FileNotFoundError(f"generated Web index not found: {WEB_INDEX_PATH}")
    STATIC_INDEX_PATH.parent.mkdir(parents=True, exist_ok=True)
    shutil.copyfile(WEB_INDEX_PATH, STATIC_INDEX_PATH)
    print(f"[refresh_stock_index] synced {WEB_INDEX_PATH} -> {STATIC_INDEX_PATH}", flush=True)


def main(argv: Sequence[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description="刷新股票自动补全索引")
    parser.add_argument(
        "--skip-fetch",
        action="store_true",
        help="跳过 Tushare 抓取,仅用现有 data/stock_list_*.csv 重新生成索引",
    )
    args = parser.parse_args(argv)

    try:
        if args.skip_fetch:
            print("[refresh_stock_index] skip Tushare fetch; using existing CSV files")
        else:

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Run the script WITHOUT --skip-fetch once so data/stock_list_*.csv is fetched and apps/dsa-web/public/stocks.index.json is generated.
  2. If fetch must be skipped, ensure data/stock_list_*.csv already exists (from a previous run) so generation can produce the index before sync.
  3. Check that apps/dsa-web/public/ exists and is writable; the generator writes the index there.
  4. If TUSHARE_TOKEN gating skipped the fetch silently, set the token (see error 180) so the full run completes.

Example fix

# before
$ python scripts/refresh_stock_index.py --skip-fetch
FileNotFoundError: generated Web index not found: .../stocks.index.json

# after
$ python scripts/refresh_stock_index.py            # full run: fetch -> generate -> sync
$ python scripts/refresh_stock_index.py --skip-fetch  # now safe, CSVs exist
Defensive patterns

Strategy: validation

Validate before calling

from scripts.refresh_stock_index import WEB_INDEX_PATH
from pathlib import Path

if not WEB_INDEX_PATH.is_file():
    raise SystemExit("Run full refresh first (no --skip-fetch) to generate stocks.index.json")

Type guard

def web_index_ready() -> bool:
    return WEB_INDEX_PATH.is_file()

Try / catch

try:
    _sync_static_index()
except FileNotFoundError:
    run_full_refresh()  # fetch + generate, then retry sync
    _sync_static_index()

Prevention

When it happens

Trigger: Running refresh_stock_index.py --skip-fetch when data/stock_list_*.csv is also absent (nothing to generate the index from, so stocks.index.json is never written); running only the sync portion; the web public dir cleaned (fresh clone, git clean, or dsa-web reinstall wiping public/).

Common situations: First run on a fresh clone without prior fetch output; CI job or wrapper invoking the script with --skip-fetch before any successful full run; stocks.index.json gitignored so a clean checkout lacks it.

Related errors


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