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(
itemView on GitHub (pinned to 5159bd72e8)
Solutions
- Rename or export the file to one of the supported suffixes: .csv, .json, or .jsonl.
- If the data lives in Excel, convert first: df = pd.read_excel(p); df.to_csv(p.with_suffix('.csv'), index=False).
- For gzipped files, decompress before passing: gzip.decompress(...) written to a .json/.csv path.
- 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
- Standardize candidate context artifacts on .csv/.json/.jsonl in the pipeline.
- Convert Excel exports at the boundary with to_csv/with_suffix('.csv').
- Validate suffixes during config load so a bad path fails fast, not mid-run.
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
- Candidate context file not found: {path}
- Unsupported daily source: {source}
- Backend executable not found: ${backendPath}
- Invalid share image record ID
- Desktop backend URL is unavailable
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/45278a3b4add15f6.
Report an issue: GitHub.