HKUDS/Vibe-Trading · error · ValueError

period must be string, got

Error message

period must be string, got {type(period).__name__}

What it means

_parse_period in alpha_bench_tool requires the period argument to be a str. Passing any other type (int, None, dict, datetime) raises this immediately, before regex matching is attempted.

Solutions

  1. Convert the value to str before calling (e.g. str(period) for scalars)
  2. Add a JSON-schema 'type':'string' constraint on the tool's period parameter
  3. Default the parameter explicitly (e.g. '2020-2023') instead of letting None through

Example fix

// before
result = alpha_bench(universe='csi300', period=None)
// after
result = alpha_bench(universe='csi300', period='2020-2023')
Defensive patterns

Strategy: type-guard

Validate before calling

period = period if isinstance(period, str) else str(period)
assert isinstance(period, str) and period

Type guard

def is_period_str(p: object) -> bool:
    return isinstance(p, str) and len(p) > 0

Try / catch

try:
    alpha_bench(universe=u, period=period)
except ValueError as e:
    if 'period must be string' in str(e):
        period = str(period); retry()
    else: raise

Prevention

When it happens

Trigger: Calling alpha_bench / kick_off_bench / kick_off_compare / _load_universe_panel with period=None, period=2023, or a pandas Timestamp / datetime object instead of a string.

Common situations: Tool schemas where the LLM emits a number for a year-only period; passing datetime objects from downstream code; optional kwargs that default to None being forwarded unconditionally.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/28643e8a17166f26. Report an issue: GitHub.

Appendix: source

Thrown at agent/src/tools/alpha_bench_tool.py:83

# Universe + period parsing
# ---------------------------------------------------------------------------

_PERIOD_YEAR = re.compile(r"^(\d{4})-(\d{4})$")
_PERIOD_DATE = re.compile(r"^(\d{4}-\d{2}-\d{2})/(\d{4}-\d{2}-\d{2})$")

# Universe → (market_key, universe_meta_tag). Only the listed universes have a
# defined contract; everything else returns "not yet implemented".
_UNIVERSE_TAG = {
    "csi300": "equity_cn",
    "sp500": "equity_us",
    "btc-usdt": "crypto",
}


def _parse_period(period: str) -> tuple[str, str]:
    """Return (start_date, end_date) as YYYY-MM-DD strings."""
    if not isinstance(period, str):
        raise ValueError(f"period must be string, got {type(period).__name__}")
    m = _PERIOD_DATE.match(period)
    if m:
        start, end = m.group(1), m.group(2)
    else:
        m = _PERIOD_YEAR.match(period)
        if m:
            start, end = f"{m.group(1)}-01-01", f"{m.group(2)}-12-31"
        else:
            raise ValueError(
                f"period {period!r} must be YYYY-YYYY or YYYY-MM-DD/YYYY-MM-DD"
            )
    # Match backtest loaders.validate_date_range: reject inverted ranges.
    if pd.Timestamp(start) > pd.Timestamp(end):
        raise ValueError(f"start_date ({start}) > end_date ({end})")
    return start, end


def _load_universe_panel(

View on GitHub (pinned to 80ffdda44c)