{"record":{"id":"0f3554a1720fb368","repo":"bmad-code-org/BMAD-METHOD","slug":"unparseable-date-raw-r-want-yyyy-mm-dd","errorCode":null,"errorMessage":"unparseable date: {raw!r} (want YYYY[-MM[-DD]])","messagePattern":"unparseable date: (.+?) \\(want YYYY\\[-MM\\[-DD\\]\\]\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/core-skills/bmad-deep-recon/scripts/recon_kit.py","lineNumber":164,"sourceCode":"        claims[status] = claims.get(status, 0) + 1\n    return out({\n        \"entries\": entries,\n        \"by_type\": dict(sorted(by_type.items())),\n        \"claims\": dict(sorted(claims.items())),\n        \"claims_total\": sum(claims.values()),\n    }, 0)\n\n\n# --- staleness ---------------------------------------------------------------\n\ndef parse_date(raw: str) -> date:\n    raw = raw.strip()\n    for fmt in (\"%Y-%m-%d\", \"%Y-%m\", \"%Y\"):\n        try:\n            return datetime.strptime(raw, fmt).date()\n        except ValueError:\n            continue\n    raise ValueError(f\"unparseable date: {raw!r} (want YYYY[-MM[-DD]])\")\n\n\ndef add_months(d: date, months: int) -> date:\n    total = d.month - 1 + months\n    year, month = d.year + total // 12, total % 12 + 1\n    return date(year, month, min(d.day, calendar.monthrange(year, month)[1]))\n\n\ndef cmd_staleness(args) -> int:\n    try:\n        payload = json.loads(read_text(args.file))\n        windows = {k.lower(): int(v) for k, v in json.loads(args.windows).items()}\n        today = parse_date(args.today) if args.today else date.today()\n    except (ValueError, json.JSONDecodeError) as e:\n        print(f\"error: {e}\", file=sys.stderr)\n        return 2\n    claims = payload[\"claims\"] if isinstance(payload, dict) else payload\n    results, no_window, stale_count = [], set(), 0","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/bmad-code-org/BMAD-METHOD/blob/b70486b9bdcb0a404d329e2a763b57964e7f1360/src/core-skills/bmad-deep-recon/scripts/recon_kit.py#L146-L182","documentation":"recon_kit.py's `parse_date` accepts only three formats — `YYYY-MM-DD`, `YYYY-MM`, or `YYYY` — tried in that order via `datetime.strptime`. If none parse, it raises this error naming the offending input. The function feeds the staleness command, where it parses both the optional `--today` argument and every claim's `pub_date`, so the message can surface from either a CLI flag or a record field.","triggerScenarios":"Passing `--today 12/08/2026` (slashes, day-first), a `pub_date` of `\"Q3 2026\"`, `\"Aug 2026\"`, `\"2026.08.12\"`, an empty string, or a two-digit year. Also a full datetime `2026-08-12T14:00` which has no matching format.","commonSituations":"Locale-formatted dates copied from a browser or spreadsheet (MM/DD/YYYY); free-text publication dates scraped from sources that don't use ISO; a missing pub_date stored as the empty string.","solutions":["Normalise the input to one of the three accepted forms; prefer `YYYY-MM-DD`.","If the value comes from `--today`, pass an explicit ISO date or omit the flag (it defaults to `date.today()`).","Pre-process claim records to canonicalise pub_date before feeding them to `staleness` (e.g. `dateutil.parser.parse(...).strftime('%Y-%m-%d')`).","Filter or flag records whose pub_date is empty or non-ISO before running the command."],"exampleFix":"# before\n--today 12/08/2026\n# claim pub_date: \"Aug 12, 2026\"\n\n# after\n--today 2026-08-12\n# claim pub_date: \"2026-08-12\"","handlingStrategy":"validation","validationCode":"from datetime import datetime\ndef is_supported_date(s: str) -> bool:\n    for fmt in (\"%Y-%m-%d\",\"%Y-%m\",\"%Y\"):\n        try: datetime.strptime(s.strip(), fmt); return True\n        except ValueError: continue\n    return False","typeGuard":"def is_iso_date(s: object) -> bool:\n    if not isinstance(s, str): return False\n    return any(_matches(s.strip(), f) for f in (\"%Y-%m-%d\",\"%Y-%m\",\"%Y\"))","tryCatchPattern":"try:\n    today = parse_date(args.today) if args.today else date.today()\nexcept ValueError as e:\n    print(f\"error: {e}\", file=sys.stderr); return 2","preventionTips":["Normalise all dates to YYYY-MM-DD at the source.","Pre-canonicalise scraped pub_dates with dateutil before feeding staleness.","Omit --today to use the default (date.today()) when in doubt."],"tags":["date","validation","recon","cli-input","data-parsing"],"backgroundTag":null,"analyzedSha":"b70486b9bdcb0a404d329e2a763b57964e7f1360","analyzedAt":"2026-08-13T01:21:12.247Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}