ZhuLinsen/daily_stock_analysis · error · ValueError
analysis_phase must be one of premarket, intraday, postmarke
Error message
analysis_phase must be one of premarket, intraday, postmarket, unknown
What it means
_normalize_phase_filter lowercases and trims the analysis_phase argument, treating None/''/'all' as no filter, and only accepts the four buckets premarket, intraday, postmarket, unknown. Anything else raises ValueError → HTTP 400 invalid_params on the results/summary/performance endpoints.
Source
Thrown at src/services/backtest_service.py:799
market_phase=bucket,
raw_result=raw_result,
report_type=report_type,
analysis_sentiment_score=analysis_sentiment_score,
)
for result, stock_name, trend_prediction, summary, bucket, raw_result, report_type, analysis_sentiment_score in page_rows
]
return {"total": matched_total, "page": page, "limit": limit, "items": items}
@staticmethod
def _normalize_phase_filter(value: Optional[str]) -> Optional[str]:
if value is None:
return None
text = str(value or "").strip().lower()
if not text or text == "all":
return None
allowed = {"premarket", "intraday", "postmarket", "unknown"}
if text not in allowed:
raise ValueError("analysis_phase must be one of premarket, intraday, postmarket, unknown")
return text
@staticmethod
def _phase_bucket_from_summary(summary: Optional[Dict[str, Any]]) -> str:
if not isinstance(summary, dict):
return "unknown"
return normalize_analysis_phase_bucket(summary.get("phase"))
@classmethod
def _phase_bucket_from_snapshot(cls, context_snapshot: Optional[str]) -> str:
return cls._phase_bucket_from_summary(extract_market_phase_summary(context_snapshot))
@classmethod
def _phase_counts_from_contexts(cls, snapshots: List[Optional[str]]) -> Dict[str, Dict[str, int]]:
phase_breakdown = {"premarket": 0, "intraday": 0, "postmarket": 0, "unknown": 0}
raw_phase_counts: Dict[str, int] = {}
for snapshot in snapshots:
summary = extract_market_phase_summary(snapshot)View on GitHub (pinned to 5159bd72e8)
Solutions
- Use exactly one of: premarket, intraday, postmarket, unknown (case-insensitive).
- Omit the parameter or pass 'all' to disable phase filtering.
- Align the web UI select options with this enum (BacktestAnalysisPhaseQuery already enumerates them in the API layer).
Example fix
# before service.get_recent_evaluations(analysis_phase="after_hours") # after service.get_recent_evaluations(analysis_phase="postmarket")
Defensive patterns
Strategy: type-guard
Validate before calling
ALLOWED_PHASES = {"premarket", "intraday", "postmarket", "unknown"}
phase_norm = (analysis_phase or "").strip().lower()
if phase_norm and phase_norm != "all":
assert phase_norm in ALLOWED_PHASES, f"bad phase: {analysis_phase}" Type guard
ALLOWED_PHASES = {"premarket", "intraday", "postmarket", "unknown"}
def isValidPhase(value: str | None) -> bool:
text = (value or "").strip().lower()
return text in ("", "all") or text in ALLOWED_PHASES Try / catch
try:
data = service.get_recent_evaluations(analysis_phase=phase)
except ValueError as exc:
if "analysis_phase" in str(exc):
return JSONResponse(status_code=400, content={"error": "invalid_phase", "allowed": sorted(ALLOWED_PHASES)})
raise Prevention
- Use the backend enum (BacktestAnalysisPhaseQuery / ALLOWED set) as the single source for UI dropdowns.
- Normalize phase input to lowercase-trimmed before sending.
- Document the 'all' sentinel for no-filter behavior.
When it happens
Trigger: Calling /api/v1/backtest/results?analysis_phase=pre-market, 'PREMARKET ' works but 'premarket/open', 'close', 'afterhours', 'ALL' variant casing is fine — concretely any value outside the set, e.g. analysis_phase=after_hours or analysis_phase=0.
Common situations: Frontend dropdown using different phase labels than the backend enum; users typing free text; passing 'All' works (case-insensitive) but 'any' or '*' does not.
Related errors
- Phase-filtered results match too many rows; narrow the analy
- invalid_params
- internal_error
- not_found
- eval_window_days must be positive
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/49d8d1f2fe9f8713.
Report an issue: GitHub.