{"record":{"id":"520314149113cac3","repo":"HKUDS/Vibe-Trading","slug":"quarter-year-year-is-outside-min-quarter-year","errorCode":null,"errorMessage":"quarter year {year} is outside {_MIN_QUARTER_YEAR}..{date.today().year + 1}","messagePattern":"quarter year (.+?) is outside (.+?)\\.\\.(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"agent/src/tools/institutional_holdings_tool.py","lineNumber":365,"sourceCode":"    \"\"\"\n    text = str(value).strip().upper().replace(\" \", \"\")\n    match = re.fullmatch(r\"(\\d{4})-?Q([1-4])\", text)\n    if match:\n        year, quarter = int(match.group(1)), int(match.group(2))\n    else:\n        match = re.fullmatch(r\"(\\d{4})-(\\d{1,2})-(\\d{1,2})\", text)\n        if not match:\n            raise ValueError(\n                f\"quarter {value!r} is not recognizable; use '2026Q1' or a quarter-end date '2026-03-31'\"\n            )\n        year, month, day = (int(g) for g in match.groups())\n        quarter = next((q for q, md in _QUARTER_ENDS.items() if md == (month, day)), None)\n        if quarter is None:\n            raise ValueError(\n                f\"quarter {value!r} is not a calendar quarter end; use 03-31, 06-30, 09-30 or 12-31\"\n            )\n    if not _MIN_QUARTER_YEAR <= year <= date.today().year + 1:\n        raise ValueError(f\"quarter year {year} is outside {_MIN_QUARTER_YEAR}..{date.today().year + 1}\")\n    month, day = _QUARTER_ENDS[quarter]\n    return f\"{year:04d}-{month:02d}-{day:02d}\"\n\n\ndef _quarter_label(period_end: Optional[str]) -> Optional[str]:\n    \"\"\"Render a ``YYYY-MM-DD`` quarter end as ``YYYYQn``, or ``None`` if unusable.\"\"\"\n    if not period_end or len(str(period_end)) < 7:\n        return None\n    text = str(period_end)\n    try:\n        year, month = int(text[:4]), int(text[5:7])\n    except ValueError:\n        return None\n    quarter = next((q for q, md in _QUARTER_ENDS.items() if md[0] == month), None)\n    return f\"{year}Q{quarter}\" if quarter else None\n\n\ndef _latest_reportable_quarter(today: Optional[date] = None) -> str:","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/institutional_holdings_tool.py#L347-L383","documentation":"After parsing, the year must fall between _MIN_QUARTER_YEAR and the current year + 1. Years outside that window — historical data before the tool's coverage or far-future quarters — are rejected before any network call.","triggerScenarios":"quarter='1990Q2' (below _MIN_QUARTER_YEAR) or '2035Q1' (beyond next year).","commonSituations":"Typos in years ('2206Q1'); querying periods predating SEC 13F electronic data; speculative future quarters beyond the allowed lookahead.","solutions":["Correct the year to a supported range","Check _MIN_QUARTER_YEAR in the module for the exact floor","Validate the year client-side before invoking the tool"],"exampleFix":"# before\nexecute(quarter=\"1998Q1\")\n# after\nexecute(quarter=\"2024Q1\")","handlingStrategy":"validation","validationCode":"from datetime import date\ny = int(q[:4])\nassert _MIN_QUARTER_YEAR <= y <= date.today().year + 1, f\"year {y} out of range\"","typeGuard":"def quarter_year_in_range(q: str, min_year: int) -> bool:\n    from datetime import date\n    try:\n        y = int(q.split(\"Q\")[0])\n    except (ValueError, IndexError):\n        return False\n    return min_year <= y <= date.today().year + 1","tryCatchPattern":"try:\n    qn = _parse_quarter(q)\nexcept ValueError as e:\n    if \"outside\" in str(e):\n        raise UserInputError(\"quarter not covered by the data source\")\n    raise","preventionTips":["Sanity-check year digits (catch typos like 2206)","Know the tool's coverage floor before querying history"],"tags":["python","date-parsing","range-check"],"backgroundTag":"value-out-of-range","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}