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

  1. Pass at least one real source name: --search reddit or --search reddit,x.
  2. If the value comes from a variable, guard in the caller: only append the flag when the variable is non-empty.
  3. 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

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


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