mvanhorn/last30days-skill · error · SystemExit

[Competitors] --competitors-list is empty.\n

Error message

[Competitors] --competitors-list is empty.\n

What it means

In the competitors-flag resolver: when --competitors-list is provided (non-None) but splitting on commas yields zero non-blank entries, the run aborts with SystemExit(2). This distinguishes 'flag absent' (None) from 'flag given but empty' — the latter is treated as a user error, not a no-op.

Source

Thrown at skills/last30days/scripts/last30days.py:1005

    - (False, 0, []) when neither flag, list, nor plan is set.
    - An explicit ``--competitors-list`` always wins; count is derived from list length.
    - ``--competitors-plan`` alone enables mode with an empty peer list; vs-routing
      fills peers from the vs-string or plan keys.
    - A numeric count outside [1, 6] is clamped with a stderr warning.
    - count <= 0 (explicit) raises SystemExit(2).
    """
    explicit_list: list[str] = []
    list_flag_provided = args.competitors_list is not None
    if list_flag_provided:
        explicit_list = [
            entity.strip()
            for entity in args.competitors_list.split(",")
            if entity.strip()
        ]
        if not explicit_list:
            sys.stderr.write("[Competitors] --competitors-list is empty.\n")
            raise SystemExit(2)

    competitors_flag = args.competitors
    list_present = bool(explicit_list)
    flag_present = competitors_flag is not None
    plan_present = bool(getattr(args, "competitors_plan", None))

    if not list_present and not flag_present and not plan_present:
        return False, 0, []

    if list_present:
        count = len(explicit_list)
        if flag_present and competitors_flag != count:
            sys.stderr.write(
                f"[Competitors] --competitors={competitors_flag} ignored; using "
                f"{count} entries from --competitors-list.\n"
            )
        if count > COMPETITORS_MAX:
            sys.stderr.write(

View on GitHub (pinned to c7460f6114)

Solutions

  1. Populate the list: --competitors-list 'Acme,Beta'.
  2. Omit the flag entirely when no explicit competitors are known (auto-discovery via --competitors N can fill them).
  3. Guard callers: only append the flag when the joined string is non-empty.

Example fix

# before
cmd += ['--competitors-list', ','.join(entities)]  # entities == []

# after
if entities:
    cmd += ['--competitors-list', ','.join(entities)]
else:
    cmd += ['--competitors', '3']
Defensive patterns

Strategy: validation

Validate before calling

entities = [e.strip() for e in raw.split(',') if e.strip()]
if raw is not None and not entities:
    raise ValueError('--competitors-list given but contains no non-empty entries')

Prevention

When it happens

Trigger: --competitors-list '' , --competitors-list ',' , or a value made only of spaces/commas. Any non-empty trimmed entry would proceed, so only fully-blank values trigger this.

Common situations: Templated commands injecting an empty variable: --competitors-list "$ENTITIES" with ENTITIES unset or empty; agent building the flag from an empty discovery result.

Related errors


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