{"record":{"id":"7816736eb6fbb8c2","repo":"nexu-io/open-design","slug":"unknown-search-source-source","errorCode":null,"errorMessage":"Unknown search source: {source}","messagePattern":"Unknown search source: (.+?)","errorType":"exception","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"design-templates/last30days/scripts/last30days.py","lineNumber":81,"sourceCode":"    for pid in pids:\n        try:\n            os.killpg(os.getpgid(pid), signal.SIGTERM)\n        except (ProcessLookupError, PermissionError, OSError):\n            continue\n\n\natexit.register(_cleanup_children)\n\n\ndef parse_search_flag(raw: str) -> 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: {source}\")\n        if normalized not in sources:\n            sources.append(normalized)\n    if not sources:\n        raise SystemExit(\"--search requires at least one source.\")\n    return sources\n\n\ndef slugify(value: str) -> str:\n    slug = re.sub(r\"[^a-z0-9]+\", \"-\", value.lower()).strip(\"-\")\n    return slug or \"last30days\"\n\n\ndef save_output(\n    report: schema.Report,\n    emit: str,\n    save_dir: str,\n    suffix: str = \"\",\n    synthesis_md: str | None = None,","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/design-templates/last30days/scripts/last30days.py#L63-L99","documentation":"parse_search_flag() tokenizes the `--search` argument by comma, lowercases/strips each token, maps it through pipeline.SEARCH_ALIAS, and rejects any token whose normalized form is not in pipeline.MOCK_AVAILABLE_SOURCES. It raises SystemExit with the offending (pre-alias) token so the user can see exactly which entry was unrecognized. This runs during CLI argument parsing, before any network or planner work.","triggerScenarios":"Passing `--search reddit,yutube` (typo), `--search google-news` (not a registered source), `--search RSS` after lowercasing yields `rss` which is not in MOCK_AVAILABLE_SOURCES, or any token not present in SEARCH_ALIAS and not a real source name.","commonSituations":"Typos; copying a source name from outdated docs; using a provider-only label (e.g. `openai`) instead of a content source; case/whitespace surprises are handled, so a residual failure is a genuinely unknown name.","solutions":["Run with `--search` omitted to use all MOCK_AVAILABLE_SOURCES, or","Pass only known source names: reddit, youtube, x, xquik, github, hackernews, polymarket, threads, truthsocial, xiaohongshu, pinterest, grounding (and any aliases defined in pipeline.SEARCH_ALIAS).","If you expected a source to exist, grep `SEARCH_ALIAS` and `MOCK_AVAILABLE_SOURCES` in lib/pipeline.py for the canonical spelling.","Correct the typo and rerun."],"exampleFix":"# before\npython3.12 last30days.py --topic x --search reddit,yutube\n# after\npython3.12 last30days.py --topic x --search reddit,youtube","handlingStrategy":"validation","validationCode":"from lib import pipeline\nVALID = set(pipeline.MOCK_AVAILABLE_SOURCES) | set(pipeline.SEARCH_ALIAS.keys())\nrequested = [s.strip().lower() for s in raw.split(',') if s.strip()]\nunknown = [s for s in requested if pipeline.SEARCH_ALIAS.get(s, s) not in pipeline.MOCK_AVAILABLE_SOURCES]\nif unknown:\n    raise ValueError(f'Unknown --search sources: {unknown}. Valid: {sorted(VALID)}')","typeGuard":null,"tryCatchPattern":"try:\n    sources = parse_search_flag(raw)\nexcept SystemExit as e:\n    print(f'fix --search: {e}', file=sys.stderr)\n    sys.exit(2)","preventionTips":["Source the valid list from pipeline.MOCK_AVAILABLE_SOURCES rather than hard-coding it.","Validate `--search` in wrapper scripts before invoking last30days."],"tags":["cli","argument-validation","python","config"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}