ZhuLinsen/daily_stock_analysis · error · ValueError
invalid analysis_phase: {requested}. Must be one of {sorted(
Error message
invalid analysis_phase: {requested}. Must be one of {sorted(_SUPPORTED_ANALYSIS_PHASES)} What it means
Trading-calendar phase resolver (_coerce/normalize step in src/core/trading_calendar.py): analysis_phase is normalized (MarketPhase enum value, else str().strip().lower(), defaulting 'auto'; legacy analysis_intent is honored when phase is 'auto') and must be one of _SUPPORTED_ANALYSIS_PHASES = {auto, premarket, intraday, postmarket}. Any other string is rejected with the allowed list embedded, because downstream market-phase context building branches on exactly these phases.
Source
Thrown at src/core/trading_calendar.py:508
return None, None, False
def _normalize_analysis_phase(
analysis_phase: Optional[str],
analysis_intent: Optional[str],
) -> str:
def _coerce(value: Optional[str]) -> str:
if isinstance(value, MarketPhase):
return value.value
return str(value or "").strip().lower()
requested = _coerce(analysis_phase) or "auto"
legacy_intent = _coerce(analysis_intent)
if requested == "auto" and legacy_intent and legacy_intent != "auto":
requested = legacy_intent
if requested not in _SUPPORTED_ANALYSIS_PHASES:
raise ValueError(
f"invalid analysis_phase: {requested}. "
f"Must be one of {sorted(_SUPPORTED_ANALYSIS_PHASES)}"
)
return requested
def build_market_phase_context(
*,
market: Optional[str],
current_time: Optional[datetime] = None,
trigger_source: str = "system",
analysis_intent: str = "auto",
analysis_phase: str = "auto",
) -> MarketPhaseContext:
"""
Build a JSON-safe runtime market-phase context for analysis plumbing.
``analysis_phase="auto"`` keeps calendar inference. Explicit supportedView on GitHub (pinned to 5159bd72e8)
Solutions
- Use one of the supported tokens exactly: auto, premarket, intraday, postmarket (lowercase after normalization; the error lists them sorted).
- If you intended the legacy intent axis, pass analysis_intent only when phase is 'auto', and use phase-supported vocabulary.
- Map custom labels to canonical phases at your call site before invoking the calendar API.
Example fix
# before build_market_phase_context(market="US", analysis_phase="pre-market") # after build_market_phase_context(market="US", analysis_phase="premarket")
Defensive patterns
Strategy: type-guard
Validate before calling
from src.core.trading_calendar import _SUPPORTED_ANALYSIS_PHASES
phase = (analysis_phase or "auto").strip().lower()
assert phase in _SUPPORTED_ANALYSIS_PHASES, f"bad phase: {phase}" Type guard
SUPPORTED = {"auto", "premarket", "intraday", "postmarket"}
def is_analysis_phase(value: str) -> bool:
return value.strip().lower() in SUPPORTED Try / catch
try:
ctx = build_market_phase_context(market="US", analysis_phase=phase)
except ValueError as exc:
logger.error("bad analysis_phase: %s", exc)
phase = "auto"
ctx = build_market_phase_context(market="US", analysis_phase=phase) Prevention
- Use only the four canonical phase tokens
- Normalize (strip+lower) user input before passing
- Keep legacy analysis_intent vocabulary separate from phase vocabulary
When it happens
Trigger: Calling build_market_phase_context (or the resolver it fronts) with analysis_phase like 'pre-market', 'PRE', 'overnight', 'close', or a typo; also triggered by legacy analysis_intent values that are not phase names when phase is auto. MarketPhase enum instances pass via .value.
Common situations: Env/CLI passing a human label instead of the canonical token; new phase names added by callers before the engine supports them; mixing up analysis_intent vocabulary (e.g. 'daily') with phase vocabulary.
Related errors
- Desktop backend origin is invalid
- Desktop window is unavailable
- Desktop share image capture returned an empty image
- capability_unsupported
- unsupported alert_type for current EventMonitor runtime: {al
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/be1cc6a94c8648d2.
Report an issue: GitHub.