{"record":{"id":"f3a495309b3c75c9","repo":"HKUDS/Vibe-Trading","slug":"start-date-must-be-yyyy-mm-dd","errorCode":null,"errorMessage":"start_date must be YYYY-MM-DD","messagePattern":"start_date must be YYYY-MM-DD","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/autopilot_tool.py","lineNumber":241,"sourceCode":"    candidate = (data_sources or [\"auto\"])[0]\n    try:\n        from backtest.loaders.registry import VALID_SOURCES\n    except Exception:  # pragma: no cover - registry import is environment-stable\n        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","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/autopilot_tool.py#L223-L259","documentation":"autopilot_tool validates backtest inputs before writing run artifacts; start_date must parse strictly as YYYY-MM-DD via datetime.strptime. Any other format (slashes, month names, YYYYMMDD) fails.","triggerScenarios":"Calling autopilot execute with start_date='2023/01/01', '01-02-2023', '20230101', or a datetime object stringified with time components.","commonSituations":"Frontend date pickers emitting locale formats; LLM-supplied dates in natural formats; ISO datetime strings ('2023-01-01T00:00:00') passed untrimmed.","solutions":["Format dates as %Y-%m-%D strictly (date.strftime('%Y-%m-%d'))","Normalize incoming datetimes to .date() then format","Add a regex pre-check r'^\\d{4}-\\d{2}-\\d{2}$' before calling the tool"],"exampleFix":"// before\nexecute(start_date='2023/01/01', ...)\n// after\nexecute(start_date='2023-01-01', ...)","handlingStrategy":"validation","validationCode":"import re\nassert re.fullmatch(r'\\d{4}-\\d{2}-\\d{2}', start_date), 'start_date must be YYYY-MM-DD'","typeGuard":"def is_iso_date(s: str) -> bool:\n    import re, datetime\n    if not re.fullmatch(r'\\d{4}-\\d{2}-\\d{2}', s or ''):\n        return False\n    try:\n        datetime.date.fromisoformat(s); return True\n    except ValueError:\n        return False","tryCatchPattern":"try:\n    _validate_backtest_dates(start_date, end_date)\nexcept ValueError as e:\n    start_date = normalize_date(start_date); retry","preventionTips":["Emit dates from date objects with strftime, never from user strings","Centralize date normalization in the API layer"],"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"}