{"record":{"id":"0706567080319c28","repo":"HKUDS/Vibe-Trading","slug":"end-date-must-be-yyyy-mm-dd","errorCode":null,"errorMessage":"end_date must be YYYY-MM-DD","messagePattern":"end_date must be YYYY-MM-DD","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/autopilot_tool.py","lineNumber":245,"sourceCode":"        return candidate, None\n    if candidate in VALID_SOURCES:\n        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    \"\"\"","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/autopilot_tool.py#L227-L263","documentation":"Companion check to the start_date validation: end_date must also parse strictly as YYYY-MM-DD before any run artifacts are written.","triggerScenarios":"Calling autopilot execute with end_date in any non-ISO format — 'Dec 31 2023', '31-12-2023', '2023/12/31', or with time/timezone suffixes.","commonSituations":"Mixed-format date pairs (one valid, one not); user-typed dates; downstream systems returning RFC 3339 timestamps.","solutions":["Convert to YYYY-MM-DD with strftime('%Y-%m-%d')","Parse flexible input with dateutil then re-format to ISO","Validate both dates with one shared helper before invoking execute"],"exampleFix":"// before\nexecute(end_date='31-12-2023', ...)\n// after\nexecute(end_date='2023-12-31', ...)","handlingStrategy":"validation","validationCode":"assert re.fullmatch(r'\\d{4}-\\d{2}-\\d{2}', end_date), 'end_date must be YYYY-MM-DD'","typeGuard":"def is_iso_end_date(s: str) -> bool:\n    import re\n    return bool(re.fullmatch(r'\\d{4}-\\d{2}-\\d{2}', s or ''))","tryCatchPattern":"try:\n    _validate_backtest_dates(start_date, end_date)\nexcept ValueError as e:\n    if 'end_date must be' in str(e):\n        end_date = normalize_date(end_date)","preventionTips":["Use one shared date-normalization helper for both bounds","Reject datetime-with-time strings at the boundary"],"tags":["date-format","validation","autopilot"],"backgroundTag":"invalid-date-format","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}