HKUDS/Vibe-Trading · error · ValueError
today must be an ISO date string or None, got {today!r}
Error message
today must be an ISO date string or None, got {today!r} What it means
Raised by _parse_today in strategy_discovery/facade.py when the optional `today` argument is neither None nor a string (e.g. a date/datetime object passed directly). The facade accepts only an ISO date string or None (None means use date.today()). Passing any other type is rejected before date.fromisoformat is attempted.
Source
Thrown at agent/src/strategy_discovery/facade.py:113
return None
return value
def _is_int(value: Any) -> bool:
"""True for real integers only (bool is explicitly excluded)."""
return isinstance(value, int) and not isinstance(value, bool)
def _parse_today(today: str | None) -> date:
"""Resolve the injected clock: ISO ``today`` string or the wall clock.
Raises ``ValueError`` for a non-string or unparseable ``today`` so the
caller can answer with an error envelope instead of a wrong date.
"""
if today is None:
return date.today()
if not isinstance(today, str):
raise ValueError(f"today must be an ISO date string or None, got {today!r}")
return date.fromisoformat(today.strip())
def _decay_fields(row, today: date) -> dict[str, Any]:
"""Read-time decay verdict for one evidence row (plan D1/D2).
Computed from the row's own ``date_ranges`` window end at query time —
never persisted. ``staleness_days`` (from ``last_verified``) is reported
alongside but NEVER gates: refreshing unchanged artifacts must not be
able to keep a row "fresh" forever.
"""
age = evidence_age_days(row.date_ranges, today)
status = classify_decay(row.date_ranges, today)
return {
"decay_status": status,
"evidence_age_days": age,
"staleness_days": staleness_days(row.last_verified, today),
"_decay_warning": decay_warning(status, age),View on GitHub (pinned to 80ffdda44c)
Solutions
- Pass today=None to use the real current date
- Pass an ISO string like '2024-01-31' (date.isoformat() output)
- If you hold a date object, convert: today=d.isoformat()
Example fix
# before facade.query_strategies(today=datetime(2024, 1, 31)) # after facade.query_strategies(today='2024-01-31')
Defensive patterns
Strategy: validation
Validate before calling
from datetime import date
if today is not None and not isinstance(today, str):
today = today.isoformat() if hasattr(today, 'isoformat') else None
assert today is None or isinstance(today, str) Type guard
def is_iso_date_or_none(v) -> bool:
if v is None: return True
if not isinstance(v, str): return False
try: date.fromisoformat(v.strip()); return True
except ValueError: return False Try / catch
try:
facade.query_strategies(today=today)
except ValueError as e:
if 'today must be' in str(e): logger.warning('bad today, retrying with None'); facade.query_strategies(today=None)
else: raise Prevention
- Always pass date.isoformat() output or None
- Never pass datetime objects directly
- Centralize today computation in one helper
When it happens
Trigger: Calling query_strategies(today=date(2024,1,1)) or get_strategy_evidence(today=datetime.now()) — passing a date/datetime object or an int instead of an ISO string like '2024-01-01' or None.
Common situations: Callers already hold a datetime/date object from another API and pass it through unconverted; or pass an int timestamp assuming the facade parses it. Note date.fromisoformat itself will still raise ValueError for malformed strings, which is not caught here.
Related errors
- quarter {value!r} is not recognizable; use '2026Q1' or a qua
- quarter {value!r} is not a calendar quarter end; use 03-31,
- quarter year {year} is outside {_MIN_QUARTER_YEAR}..{date.to
- invalid alpha_id
- alpha_id not found
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/5f9ae35658c6d40e.
Report an issue: GitHub.