{"record":{"id":"8df2e8b9e1b958b1","repo":"mvanhorn/last30days-skill","slug":"field-subqueries-must-be-a-non-empty-array","errorCode":null,"errorMessage":"field 'subqueries' must be a non-empty array","messagePattern":"field 'subqueries' must be a non-empty array","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/last30days/scripts/lib/planner.py","lineNumber":191,"sourceCode":"            raise ValueError(f\"missing required field '{field}'\")\n    for field in (\"intent\", \"freshness_mode\", \"cluster_mode\"):\n        if not isinstance(raw[field], str) or not raw[field].strip():\n            raise ValueError(f\"field '{field}' must be a non-empty string\")\n\n    source_weights = raw.get(\"source_weights\")\n    if source_weights is not None and not isinstance(source_weights, dict):\n        raise ValueError(\"field 'source_weights' must be an object when provided\")\n    for source, weight in (source_weights or {}).items():\n        if (\n            not isinstance(source, str)\n            or not source.strip()\n            or isinstance(weight, bool)\n            or not isinstance(weight, (int, float))\n        ):\n            raise ValueError(\"field 'source_weights' must map source names to numbers\")\n    subqueries = raw[\"subqueries\"]\n    if not isinstance(subqueries, list) or not subqueries:\n        raise ValueError(\"field 'subqueries' must be a non-empty array\")\n    for index, subquery in enumerate(subqueries):\n        if not isinstance(subquery, dict):\n            raise ValueError(f\"subqueries[{index}] must be an object\")\n        for field in (\"search_query\", \"ranking_query\"):\n            if not isinstance(subquery.get(field), str) or not subquery[field].strip():\n                raise ValueError(f\"subqueries[{index}].{field} must be a non-empty string\")\n        sources = subquery.get(\"sources\")\n        if not isinstance(sources, list) or not sources or not all(\n            isinstance(source, str) and source.strip() for source in sources\n        ):\n            raise ValueError(f\"subqueries[{index}].sources must be a non-empty string array\")\n        weight = subquery.get(\"weight\")\n        if weight is not None and (\n            isinstance(weight, bool) or not isinstance(weight, (int, float))\n        ):\n            raise ValueError(f\"subqueries[{index}].weight must be a number when provided\")\n\n","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/skills/last30days/scripts/lib/planner.py#L173-L209","documentation":"validate_external_plan requires 'subqueries' to be a non-empty list. An empty plan with zero subqueries, a dict of subqueries keyed by name, or a bare string all fail here. At least one subquery is mandatory because it defines the actual search work; a plan with nothing to run is meaningless.","triggerScenarios":"\"subqueries\": [] or \"subqueries\": {} or \"subqueries\": \"q: rust compilers\" in the external plan.","commonSituations":"LLM generating an empty array when it finds nothing worth searching; template scaffolds left unpopulated; subqueries accidentally nested one level too deep so the top field is empty.","solutions":["Provide at least one subquery object with search_query, ranking_query, and sources.","If the generator produced none, fall back to letting the planner build the plan instead of passing external_plan.","Guard in your emitter: if not plan['subqueries']: skip the external plan."],"exampleFix":"# before\n\"subqueries\": []\n\n# after\n\"subqueries\": [{\"search_query\": \"rust compilers\", \"ranking_query\": \"rust compiler performance\", \"sources\": [\"reddit\", \"hackernews\"]}]","handlingStrategy":"validation","validationCode":"sq = plan[\"subqueries\"]\nif not isinstance(sq, list) or not sq:\n    raise SystemExit(\"external plan needs >= 1 subquery\")","typeGuard":"def is_nonempty_subquery_list(v) -> bool:\n    return isinstance(v, list) and len(v) > 0 and all(isinstance(q, dict) for q in v)","tryCatchPattern":null,"preventionTips":["If your generator produces zero subqueries, skip the external plan and let the planner build one.","Assert len(plan['subqueries']) >= 1 before calling run_pipeline."],"tags":["planner","external-plan","validation","json"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}