HKUDS/Vibe-Trading · error · TushareFallbackUnavailable
invalid date for tushare fallback: {value!r}
Error message
invalid date for tushare fallback: {value!r} What it means
_compact_date normalizes a date string for Tushare's YYYYMMDD API format; it strips dashes then requires exactly 8 digits. It raises TushareFallbackUnavailable when the value doesn't reduce to 8 digits — for example '2024/01/05' (slashes survive), '2024-1-5' (only 6 digits), or arbitrary text like 'latest'.
Source
Thrown at agent/src/tools/tushare_fallbacks.py:49
def _records(frame: Any) -> list[dict[str, Any]]:
if frame is None:
return []
if bool(getattr(frame, "empty", False)):
return []
if hasattr(frame, "to_dict"):
rows = frame.to_dict("records")
return [row for row in rows if isinstance(row, dict)]
if isinstance(frame, list):
return [row for row in frame if isinstance(row, dict)]
return []
def _compact_date(value: str) -> str:
digits = str(value).strip().replace("-", "")
if len(digits) != 8 or not digits.isdigit():
raise TushareFallbackUnavailable(f"invalid date for tushare fallback: {value!r}")
return digits
def _dashed_date(value: Any) -> str | None:
if value is None:
return None
digits = str(value).strip().replace("-", "")
if len(digits) == 8 and digits.isdigit():
return f"{digits[:4]}-{digits[4:6]}-{digits[6:]}"
return str(value)[:10] if value else None
def _date_window(days: int) -> tuple[str, str]:
end = date.today()
# Market holidays/weekends mean calendar days need slack to recover the
# requested number of trading rows.
start = end - timedelta(days=max(days * 3, 10))
return start.strftime("%Y%m%d"), end.strftime("%Y%m%d")View on GitHub (pinned to 80ffdda44c)
Solutions
- Normalize the date to 'YYYY-MM-DD' or 'YYYYMMDD' before calling fetch_dragon_tiger
- Validate/parse user-supplied dates at the boundary (e.g. datetime.date.isoformat())
- Default missing dates to a computed trade date instead of passing raw input through
- Catch TushareFallbackUnavailable and surface a clear 'expected YYYY-MM-DD' message
Example fix
# before
fetch_dragon_tiger(trade_date="2024/06/01")
# after
from datetime import datetime
date = datetime.strptime("2024/06/01", "%Y/%m/%d").strftime("%Y-%m-%d")
fetch_dragon_tiger(trade_date=date) Defensive patterns
Strategy: validation
Validate before calling
import re
def is_valid_trade_date(value: str) -> bool:
digits = str(value).strip().replace('-', '')
return bool(re.fullmatch(r'\d{8}', digits))
assert is_valid_trade_date(trade_date), f'bad date: {trade_date!r}' Type guard
def is_iso_date(value: str) -> bool:
"""Type-level guard for 'YYYY-MM-DD' strings accepted by the fallback."""
import re
return isinstance(value, str) and bool(re.fullmatch(r'\d{4}-\d{2}-\d{2}|\d{8}', value)) Try / catch
try:
rows = fetch_dragon_tiger(trade_date=raw)
except TushareFallbackUnavailable as exc:
if 'invalid date' in str(exc):
raise ValueError(f'expected YYYY-MM-DD, got {raw!r}') from exc
raise Prevention
- Normalize dates once at the boundary: datetime.strptime(...).strftime('%Y-%m-%d')
- Never pass user input straight through to date parameters
- Centralize date validation in one helper reused across fetchers
When it happens
Trigger: fetch_dragon_tiger (and any caller of _compact_date) passing a date like '2024/06/01', '2024060', '202406011', 'today', or None coerced to the string 'None'. Only plain 'YYYY-MM-DD' or 'YYYYMMDD' forms pass.
Common situations: Dates sourced from user input or another API with a different format (slashes, abbreviated months); empty string defaults; a date already normalized by a different layer producing a non-8-digit result; timezone/locale-specific formatting.
Related errors
- alpha_id not found
- period {period!r} must be YYYY-YYYY or YYYY-MM-DD/YYYY-MM-DD
- start_date must be YYYY-MM-DD
- end_date must be YYYY-MM-DD
- invalid date: {date!r}; expected YYYY-MM-DD
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/3875c465239b504c.
Report an issue: GitHub.