mvanhorn/last30days-skill · error · SystemExit
{flag_name} requires at least one source.
Error message
{flag_name} requires at least one source. What it means
parse_search_flag() raises SystemExit when, after splitting the raw --search value on commas and dropping empty/whitespace-only tokens, zero valid sources remain — i.e. the flag was passed but effectively empty.
Source
Thrown at skills/last30days/scripts/last30days.py:98
continue
atexit.register(_cleanup_children)
def parse_search_flag(raw: str, flag_name: str = "--search") -> list[str]:
sources = []
for source in raw.split(","):
source = source.strip().lower()
if not source:
continue
normalized = pipeline.SEARCH_ALIAS.get(source, source)
if normalized not in pipeline.MOCK_AVAILABLE_SOURCES:
raise SystemExit(f"Unknown search source in {flag_name}: {source}")
if normalized not in sources:
sources.append(normalized)
if not sources:
raise SystemExit(f"{flag_name} requires at least one source.")
return sources
def parse_as_of_date_arg(value: str) -> str:
try:
parsed = dates.parse_as_of_date(value)
except ValueError as exc:
raise argparse.ArgumentTypeError(str(exc)) from exc
return parsed
def resolve_requested_sources(args_search: str | None, config: dict) -> list[str] | None:
"""Resolve the requested source set: explicit --search wins, then the
LAST30DAYS_DEFAULT_SEARCH config key (env var or .env file), then None
(per-query default behavior). The config fallback lets users pin a fixed
source set that survives upgrades without patching SKILL.md (#442).
"""
if args_search:
return parse_search_flag(args_search)
default_search = (config.get("LAST30DAYS_DEFAULT_SEARCH") or "").strip()View on GitHub (pinned to c7460f6114)
Solutions
- Pass at least one real source name: --search reddit or --search reddit,x.
- If the value comes from a variable, guard in the caller: only append the flag when the variable is non-empty.
- Check for stray quotes: --search "" is an empty request, not 'all sources'.
Example fix
# before
cmd = ['python3', 'last30days.py', topic, '--search', sources_var]
# after
cmd = ['python3', 'last30days.py', topic]
if sources_var:
cmd += ['--search', sources_var] Defensive patterns
Strategy: validation
Validate before calling
tokens = [t.strip().lower() for t in raw.split(',') if t.strip()]
if not tokens:
raise ValueError('--search value resolves to zero sources; omit the flag or name a source') Prevention
- Only append --search to command lists when the value variable is non-empty.
- Treat an empty sources variable as 'omit flag' in template code, never as an empty string argument.
When it happens
Trigger: --search '' , --search ',' , or --search ' , , ' — every comma-separated token is blank, so the sources list stays empty and the guard fires.
Common situations: Shell quoting bugs where an unset variable expands to empty string ($SEARCH_SOURCES unset); agent scripts templating the flag from a config key that is blank; trailing-comma lists built by string join over an empty list.
Related errors
- Unknown search source in {flag_name}: {source}
- Unsupported emit mode: {emit}
- [Competitors] --competitors-list is empty.\n
- [Competitors] --competitors must be >= {COMPETITORS_MIN} (go
- [last30days] Cannot read --synthesis-file: {exc}\n
AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15).
Data as JSON: /api/errors/07a704d86eab984e.
Report an issue: GitHub.