ZhuLinsen/daily_stock_analysis · error · ValueError

Unsupported candidate context file format: {path}

Error message

Unsupported candidate context file format: {path}

What it means

ValueError raised by _load_candidate_context_rows when the file suffix is not .csv, .jsonl, or .json — the only three formats the candidate-context loader parses. The error fires purely on extension, so a valid CSV named .txt or .xlsx raises before any content is read.

Source

Thrown at src/services/screening/context.py:437

                if isinstance(item, dict):
                    rows.append(item)
        return rows
    if suffix == ".json":
        data = json.loads(path.read_text(encoding="utf-8"))
        if isinstance(data, list):
            return [item for item in data if isinstance(item, dict)]
        if isinstance(data, dict):
            items = data.get("items") or data.get("data")
            if isinstance(items, list):
                return [item for item in items if isinstance(item, dict)]
            rows = []
            for code, value in data.items():
                if isinstance(value, dict):
                    rows.append({"code": code, **value})
                elif isinstance(value, str):
                    rows.append({"code": code, "text": value})
            return rows
    raise ValueError(f"Unsupported candidate context file format: {path}")


def _safe_context_value(value: object, *, max_len: int = 280) -> str:
    if value is None:
        return ""
    if isinstance(value, list):
        text = ",".join(str(item).strip() for item in value if str(item).strip())
    else:
        text = str(value).strip()
    if not text or text.lower() in {"nan", "none", "<na>"}:
        return ""
    return text[:max_len]


def _format_profile_value(value: object) -> str:
    if isinstance(value, list):
        return ",".join(
            item

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Rename or export the file to one of the supported suffixes: .csv, .json, or .jsonl.
  2. If the data lives in Excel, convert first: df = pd.read_excel(p); df.to_csv(p.with_suffix('.csv'), index=False).
  3. For gzipped files, decompress before passing: gzip.decompress(...) written to a .json/.csv path.
  4. Validate extensions before the run: assert Path(p).suffix.lower() in {'.csv', '.json', '.jsonl'} with a clear message.

Example fix

# before
read_candidate_context_files(['watchlist.xlsx'], df)  # ValueError

# after: convert once at the boundary
watch = pd.read_excel('watchlist.xlsx')
watch.to_csv('watchlist.csv', index=False)
read_candidate_context_files(['watchlist.csv'], df)
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
SUPPORTED = {'.csv', '.json', '.jsonl'}
bad = [p for p in candidate_context_paths if Path(p).suffix.lower() not in SUPPORTED]
if bad:
    raise ValueError(f'candidate context must be .csv/.json/.jsonl: {bad}')

Type guard

from pathlib import Path
def is_supported_context_file(path: str | Path) -> bool:
    return Path(path).suffix.lower() in {'.csv', '.json', '.jsonl'}

Prevention

When it happens

Trigger: Passing a candidate context file with an unsupported extension: .txt, .xlsx, .tsv, .md, or no suffix at all. The suffix check (path.suffix.lower()) dispatches format parsing, and everything outside the three handled branches falls through to the raise at src/services/screening/context.py:437.

Common situations: Users exporting Excel (.xlsx) from a data team; renaming files to .txt; uppercase extensions work (.CSV is fine via .lower()) but compressed variants (.json.gz, .csv.gz) do not; a path whose trailing dot or query string corrupts the suffix.

Related errors


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