{"record":{"id":"2ea6fc6e6a3fb7ab","repo":"HKUDS/Vibe-Trading","slug":"start-date-must-be-on-or-before-end-date","errorCode":null,"errorMessage":"start_date must be on or before end_date","messagePattern":"start_date must be on or before end_date","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/autopilot_tool.py","lineNumber":247,"sourceCode":"        return candidate, None\n    return \"auto\", (\n        f\"hypothesis data_source {candidate!r} is not a known loader source; \"\n        \"fell back to 'auto'\"\n    )\n\n\ndef _validate_backtest_dates(start_date: str, end_date: str) -> None:\n    \"\"\"Validate backtest dates before writing any run artifacts.\"\"\"\n    try:\n        start = datetime.strptime(start_date, \"%Y-%m-%d\").date()\n    except ValueError as exc:\n        raise ValueError(\"start_date must be YYYY-MM-DD\") from exc\n    try:\n        end = datetime.strptime(end_date, \"%Y-%m-%d\").date()\n    except ValueError as exc:\n        raise ValueError(\"end_date must be YYYY-MM-DD\") from exc\n    if start > end:\n        raise ValueError(\"start_date must be on or before end_date\")\n\n\ndef _run_dir_for_hypothesis(hypothesis_id: str) -> Path:\n    \"\"\"Return a path-contained run directory for any persisted hypothesis id.\"\"\"\n    suffix = hashlib.sha256(hypothesis_id.encode(\"utf-8\")).hexdigest()[:12]\n    return Path.home() / \".vibe-trading\" / \"runs\" / f\"autopilot_{suffix}\"\n\n\nclass GenerateBacktestConfigTool(BaseTool):\n    \"\"\"Generate backtest config.json from a research hypothesis.\n\n    Reads a hypothesis, derives config fields from its universe and\n    data_sources, and writes a ready-to-run config.json to a run directory.\n    The agent should then create signal_engine.py from the signal_definition\n    and call the backtest tool.\n    \"\"\"\n\n    name = \"generate_backtest_config\"","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/autopilot_tool.py#L229-L265","documentation":"Final date check in _validate_backtest_dates: after both dates parse successfully, start must not be after end. Inverted ranges would produce empty or nonsensical backtests, so they are rejected up front.","triggerScenarios":"Calling autopilot execute with start_date='2024-01-01' and end_date='2023-12-31' — both well-formed but ordered wrongly.","commonSituations":"Parameter order swaps in wrapper code; date pickers returning (to, from); LLM misordering 'from'/'to' fields.","solutions":["Swap the arguments so the earlier date is start_date","Order programmatically: start, end = sorted([start, end])","Assert ordering in tests that exercise the execute path"],"exampleFix":"// before\nexecute(start_date=end, end_date=start)\n// after\nexecute(start_date=start, end_date=end)","handlingStrategy":"validation","validationCode":"from datetime import date\nsd, ed = date.fromisoformat(start_date), date.fromisoformat(end_date)\nassert sd <= ed","typeGuard":"def dates_ordered(s: str, e: str) -> bool:\n    from datetime import date\n    return date.fromisoformat(s) <= date.fromisoformat(e)","tryCatchPattern":"try:\n    _validate_backtest_dates(start_date, end_date)\nexcept ValueError as e:\n    if 'on or before' in str(e):\n        start_date, end_date = end_date, start_date","preventionTips":["Sort date pairs once at the caller","Test the inverted-range case explicitly"],"tags":["date-validation","autopilot"],"backgroundTag":"inverted-date-range","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}