HKUDS/Vibe-Trading · error · ValueError

quarter {value!r} is not recognizable; use '2026Q1' or a qua

Error message

quarter {value!r} is not recognizable; use '2026Q1' or a quarter-end date '2026-03-31'

What it means

_parse_quarter accepts 'YYYYQn' (with optional hyphen) or 'YYYY-MM-DD' strings; anything not matching either regex raises this with usage guidance. It normalizes quarter inputs for the institutional holdings tool.

Source

Thrown at agent/src/tools/institutional_holdings_tool.py:355

    Args:
        value: The raw ``quarter`` argument.

    Returns:
        The quarter-end date as ``YYYY-MM-DD``.

    Raises:
        ValueError: When the text is not a recognizable quarter, the year is
            outside ``1993..current+1``, or the date is not a quarter end.
    """
    text = str(value).strip().upper().replace(" ", "")
    match = re.fullmatch(r"(\d{4})-?Q([1-4])", text)
    if match:
        year, quarter = int(match.group(1)), int(match.group(2))
    else:
        match = re.fullmatch(r"(\d{4})-(\d{1,2})-(\d{1,2})", text)
        if not match:
            raise ValueError(
                f"quarter {value!r} is not recognizable; use '2026Q1' or a quarter-end date '2026-03-31'"
            )
        year, month, day = (int(g) for g in match.groups())
        quarter = next((q for q, md in _QUARTER_ENDS.items() if md == (month, day)), None)
        if quarter is None:
            raise ValueError(
                f"quarter {value!r} is not a calendar quarter end; use 03-31, 06-30, 09-30 or 12-31"
            )
    if not _MIN_QUARTER_YEAR <= year <= date.today().year + 1:
        raise ValueError(f"quarter year {year} is outside {_MIN_QUARTER_YEAR}..{date.today().year + 1}")
    month, day = _QUARTER_ENDS[quarter]
    return f"{year:04d}-{month:02d}-{day:02d}"


def _quarter_label(period_end: Optional[str]) -> Optional[str]:
    """Render a ``YYYY-MM-DD`` quarter end as ``YYYYQn``, or ``None`` if unusable."""
    if not period_end or len(str(period_end)) < 7:
        return None

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Format as '2026Q1' or '2026-03-31' before calling
  2. Map fiscal labels to calendar quarters upstream
  3. Catch ValueError and re-prompt with the accepted formats

Example fix

# before
execute(quarter="Q1 2026")
# after
execute(quarter="2026Q1")
Defensive patterns

Strategy: validation

Validate before calling

import re
m = re.fullmatch(r"(\d{4})-?Q([1-4])", q) or re.fullmatch(r"(\d{4})-(\d{1,2})-(\d{1,2})", q)
assert m, f"bad quarter {q!r}; use '2026Q1' or '2026-03-31'"

Type guard

def is_parseable_quarter(q: str) -> bool:
    import re
    return bool(re.fullmatch(r"\d{4}-?Q[1-4]", q) or re.fullmatch(r"\d{4}-\d{1,2}-\d{1,2}", q))

Try / catch

try:
    qn = _parse_quarter(user_q)
except ValueError as e:
    if "not recognizable" in str(e):
        qn = normalize_quarter_string(user_q)  # map 'Q1 2026' -> '2026Q1'
    else:
        raise

Prevention

When it happens

Trigger: Passing quarter='Q1 2026', '2026/q1', 'Mar 2026', '2026-3-31' with non-2-digit forms is OK for digits, but '2026Q5', 'first quarter', or '20260331' fail the fullmatch.

Common situations: LLM or user supplying natural-language quarters, fiscal quarter labels ('FY26Q1' with prefix), or concatenated date formats.

Related errors


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