{"record":{"id":"8769db4768cef85b","repo":"nexu-io/open-design","slug":"search-requires-at-least-one-source","errorCode":null,"errorMessage":"--search requires at least one source.","messagePattern":"--search requires at least one source\\.","errorType":"exception","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"design-templates/last30days/scripts/last30days.py","lineNumber":85,"sourceCode":"            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,\n) -> Path:\n    from datetime import datetime\n    path = Path(save_dir).expanduser().resolve()\n    path.mkdir(parents=True, exist_ok=True)","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/design-templates/last30days/scripts/last30days.py#L67-L103","documentation":"parse_search_flag() raises SystemExit('--search requires at least one source.') when, after splitting/lowering/stripping/filtering empty tokens, the resulting sources list is empty. This catches `--search ''`, `--search ','`, and `--search '  '` — the flag was provided but yielded no usable source. It fires after the unknown-source check, so all surviving tokens were valid but there were zero of them.","triggerScenarios":"`--search \"\"`, `--search ,,,`, or `--search \" \"` passed on the command line. The empty-string branch (`if not source: continue`) skips every token, leaving `sources == []`, which trips the final guard.","commonSituations":"Shell-quoting accident that passes an empty value; a script templating `--search $LIST` with LIST unset; a user who thought the flag was boolean and supplied an empty string.","solutions":["Either omit `--search` entirely (defaults to all available sources), or","Supply at least one valid source: `--search reddit`.","If driven by a shell variable, default it: `--search \"${LIST:-reddit}\"`."],"exampleFix":"# before\npython3.12 last30days.py --topic x --search \"$LIST\"   # LIST unset -> ''\n# after\npython3.12 last30days.py --topic x --search \"${LIST:-reddit}\"","handlingStrategy":"validation","validationCode":"tokens = [t.strip().lower() for t in raw.split(',') if t.strip()]\nif not tokens:\n    raise ValueError('--search needs at least one source (or omit the flag)')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default unset list variables in shell: `${LIST:-reddit}`.","Omit --search entirely when you want all sources."],"tags":["cli","argument-validation","python"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}