mvanhorn/last30days-skill · error · ValueError

Invalid --as-of date: {as_of_date}. Expected YYYY-MM-DD.

Error message

Invalid --as-of date: {as_of_date}. Expected YYYY-MM-DD.

What it means

`lib/dates.py:normalize_as_of_date` raises this ValueError when `--as-of` cannot be parsed by `datetime.strptime(value, "%Y-%m-%d")`. The message echoes the offending value and the expected format, and chains the original strptime exception. Any deviation — slashes, month names, 2-digit years, or a semantically invalid date like 2026-02-30 — fails.

Source

Thrown at skills/last30days/scripts/lib/dates.py:28

    Args:
        as_of_date: Date string in YYYY-MM-DD format.

    Returns:
        Normalized YYYY-MM-DD string, or None when no date was provided.

    Raises:
        ValueError: If the date is not in YYYY-MM-DD format.
    """
    if as_of_date is None:
        return None

    if not as_of_date.strip():
        raise ValueError("--as-of must be in YYYY-MM-DD format.")

    try:
        parsed = datetime.strptime(as_of_date, "%Y-%m-%d").date()
    except ValueError as exc:
        raise ValueError(
            f"Invalid --as-of date: {as_of_date}. Expected YYYY-MM-DD."
        ) from exc

    return parsed.isoformat()


def get_date_range(days: int = 30, as_of_date: Optional[str] = None) -> Tuple[str, str]:
    """Get the date range for the last N days.

    When as_of_date is provided, the range ends at that date instead of today.

    Args:
        days: Number of days to look back.
        as_of_date: Optional end date in YYYY-MM-DD format.

    Returns:
        Tuple of (from_date, to_date) as YYYY-MM-DD strings.
    """

View on GitHub (pinned to c7460f6114)

Solutions

  1. Pass an ISO date: `--as-of 2026-07-14` (zero-padded, dashes).
  2. In scripts, generate it with `date +%F` (or `date -I`), not a locale-dependent format.
  3. Pre-validate in Python: `datetime.strptime(value, '%Y-%m-%d')` in a try/except before invoking the CLI.

Example fix

# before
--as-of 07/14/2026
# after
--as-of $(date -d '14 days ago' +%F)
Defensive patterns

Strategy: validation

Validate before calling

from datetime import datetime

def valid_as_of(value: str) -> bool:
    try:
        datetime.strptime(value, "%Y-%m-%d")
        return True
    except ValueError:
        return False

if not valid_as_of(as_of):
    raise SystemExit(f"bad --as-of {as_of!r}; expected YYYY-MM-DD")

Try / catch

from lib.dates import normalize_as_of_date
try:
    as_of = normalize_as_of_date(user_input)
except ValueError as exc:
    print(f"date rejected: {exc}", file=sys.stderr)
    sys.exit(2)

Prevention

When it happens

Trigger: `--as-of 07/14/2026`, `--as-of 2026-7-4` (non-zero-padded), `--as-of July 14 2026`, `--as-of 2026-02-30`, or any locale-formatted date string. strptime's %Y-%m-%d requires zero-padded, exactly-formatted ISO dates.

Common situations: Users copying dates from regional formats (US MM/DD/YYYY); scripts producing `date +%m/%d/%Y`; pandas/dateutil-style outputs ('2026-07-14 00:00:00') passed untrimmed; LLM hosts generating a 'natural' date.

Related errors


AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15). Data as JSON: /api/errors/f3ccdfdadc5313c5. Report an issue: GitHub.