{"record":{"id":"0b62b291f4913789","repo":"mvanhorn/last30days-skill","slug":"unknown-search-source-in-flag-name-source","errorCode":null,"errorMessage":"Unknown search source in {flag_name}: {source}","messagePattern":"Unknown search source in (.+?): (.+?)","errorType":"validation","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"skills/last30days/scripts/last30days.py","lineNumber":94,"sourceCode":"                os.killpg(os.getpgid(pid), signal.SIGTERM)\n            else:\n                os.kill(pid, signal.SIGTERM)\n        except (ProcessLookupError, PermissionError, OSError):\n            continue\n\n\natexit.register(_cleanup_children)\n\n\ndef parse_search_flag(raw: str, flag_name: str = \"--search\") -> list[str]:\n    sources = []\n    for source in raw.split(\",\"):\n        source = source.strip().lower()\n        if not source:\n            continue\n        normalized = pipeline.SEARCH_ALIAS.get(source, source)\n        if normalized not in pipeline.MOCK_AVAILABLE_SOURCES:\n            raise SystemExit(f\"Unknown search source in {flag_name}: {source}\")\n        if normalized not in sources:\n            sources.append(normalized)\n    if not sources:\n        raise SystemExit(f\"{flag_name} requires at least one source.\")\n    return sources\n\ndef parse_as_of_date_arg(value: str) -> str:\n    try:\n        parsed = dates.parse_as_of_date(value)\n    except ValueError as exc:\n        raise argparse.ArgumentTypeError(str(exc)) from exc\n    return parsed\n\ndef resolve_requested_sources(args_search: str | None, config: dict) -> list[str] | None:\n    \"\"\"Resolve the requested source set: explicit --search wins, then the\n    LAST30DAYS_DEFAULT_SEARCH config key (env var or .env file), then None\n    (per-query default behavior). The config fallback lets users pin a fixed\n    source set that survives upgrades without patching SKILL.md (#442).","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/skills/last30days/scripts/last30days.py#L76-L112","documentation":"parse_search_flag() validates each comma-separated entry of --search (and sibling flags) against pipeline.MOCK_AVAILABLE_SOURCES after applying SEARCH_ALIAS normalization. Any token that is neither a known source name nor a registered alias aborts with SystemExit before the run starts.","triggerScenarios":"Passing e.g. --search reddit,mmaspace or a typo like 'reditt'; using a source name that only exists in a newer/older engine revision; passing a platform token that requires normalization not present in SEARCH_ALIAS (case is handled by .lower(), but new/renamed sources are not).","commonSituations":"Typos in agent-authored CLI args; a source renamed between skill versions (e.g. 'twitter' vs 'x' if the alias was removed); SKILL.md examples drifting from the engine's source list.","solutions":["Run the engine's help or inspect pipeline.MOCK_AVAILABLE_SOURCES / SEARCH_ALIAS to list valid source tokens and aliases.","Correct or remove the offending token from the --search value in your command.","If you expected the source to exist, update the installed skill copy (npx skills add . -g -y) — your frozen ~/.agents/skills copy may be older than the docs you read."],"exampleFix":"# before\n--search reddit,hackernews,mmaspace\n\n# after\n--search reddit,hackernews","handlingStrategy":"validation","validationCode":"from lib import pipeline\nvalid = set(pipeline.MOCK_AVAILABLE_SOURCES) | set(pipeline.SEARCH_ALIAS)\nrequested = [s.strip().lower() for s in raw.split(',') if s.strip()]\nunknown = [s for s in requested if s not in valid and pipeline.SEARCH_ALIAS.get(s, s) not in pipeline.MOCK_AVAILABLE_SOURCES]\nassert not unknown, f'unknown sources: {unknown}'","typeGuard":"def is_known_source(token: str) -> TypeGuard[str]:\n    t = token.strip().lower()\n    return pipeline.SEARCH_ALIAS.get(t, t) in pipeline.MOCK_AVAILABLE_SOURCES","tryCatchPattern":null,"preventionTips":["Read the valid source list from the engine itself (pipeline.MOCK_AVAILABLE_SOURCES) instead of docs.","Re-sync the installed skill copy after upgrades so aliases match the docs."],"tags":["cli","validation","arguments","sources"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}