mvanhorn/last30days-skill · error · ValueError
--as-of must be in YYYY-MM-DD format.
Error message
--as-of must be in YYYY-MM-DD format.
What it means
`lib/dates.py:normalize_as_of_date` raises this ValueError when the `--as-of` argument is a non-None string that is empty or only whitespace. The function treats None as 'no date' (returns None) but a blank string as user error: the flag was passed with no usable value. Callers surface it as a CLI argument error.
Source
Thrown at skills/last30days/scripts/lib/dates.py:23
def parse_as_of_date(as_of_date: Optional[str]) -> Optional[str]:
"""Validate and normalize an --as-of date.
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.View on GitHub (pinned to c7460f6114)
Solutions
- Omit the `--as-of` flag entirely when you want 'today' behavior (None is accepted and means no as-of override).
- If scripting, guard before invoking: only append the flag when the variable is non-empty (`[ -n "$DATE" ] && args+=(--as-of "$DATE")`).
- If a date was intended, pass a real `YYYY-MM-DD` value (which then goes through the strptime check for error 22).
Example fix
# before
python3 last30days.py "topic" --as-of "$AS_OF" # AS_OF unset -> blank string
# after
python3 last30days.py "topic" ${AS_OF:+--as-of "$AS_OF"} Defensive patterns
Strategy: validation
Validate before calling
def as_of_args(value: str | None) -> list[str]:
if value is None:
return []
if not value.strip():
raise SystemExit("--as-of must be a YYYY-MM-DD date; pass nothing to use today")
return ["--as-of", value.strip()] Try / catch
try:
normalized = normalize_as_of_date(raw)
except ValueError as exc:
# treat blank input the same as absent
if "must be in YYYY-MM-DD" in str(exc):
normalized = None
else:
raise Prevention
- Only append --as-of to your command when the date variable is truthy.
- Treat blank as 'omit the flag' at the wrapper layer, since the engine treats blank as an error by design.
When it happens
Trigger: Running with `--as-of ''`, `--as-of " "`, or a shell expansion that yields an empty string (e.g. `--as-of "$AS_OF"` with the env var unset and `set -u` not in effect).
Common situations: Scripts templating `--as-of $DATE` where DATE failed to populate; CI pipelines passing a computed date that came out empty; wrapping the CLI in another tool that forwards an optional flag even when the value is blank.
Related errors
- Invalid --as-of date: {as_of_date}. Expected YYYY-MM-DD.
- Unknown search source in {flag_name}: {source}
- {flag_name} requires at least one source.
- Unsupported emit mode: {emit}
- [Competitors] --competitors-list is empty.\n
AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15).
Data as JSON: /api/errors/d470356649f06e9b.
Report an issue: GitHub.