{"record":{"id":"0735ea5c385fe87a","repo":"mvanhorn/last30days-skill","slug":"subqueries-index-field-must-be-a-non-empty-st","errorCode":null,"errorMessage":"subqueries[{index}].{field} must be a non-empty string","messagePattern":"subqueries\\[(.+?)\\]\\.(.+?) must be a non-empty string","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/last30days/scripts/lib/planner.py","lineNumber":197,"sourceCode":"    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\nDEFAULT_INTENT_CAPABILITIES = {\n    \"comparison\": {\"discussion\", \"video\", \"web\", \"reference\", \"social\", \"link\", \"market\"},\n    \"how_to\": {\"discussion\", \"video\", \"web\", \"reference\", \"link\"},\n}\n\n","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/skills/last30days/scripts/lib/planner.py#L179-L215","documentation":"Field check inside each subquery object: 'search_query' and 'ranking_query' must both be non-empty strings (after strip). Both are required per subquery — search_query drives retrieval, ranking_query drives relevance scoring, so one without the other is an incomplete contract.","triggerScenarios":"A subquery missing ranking_query, or with search_query: \"\" / \"   \" / null / a number. The error names the index and the failing field.","commonSituations":"Generators that only fill search_query and skip ranking_query; whitespace placeholder values; nulls for 'no ranking needed'.","solutions":["Set ranking_query equal to search_query if you have no separate ranking terms.","Reject/repair subqueries where either field is missing or blank before submitting.","Validate in your emitter: all(isinstance(sq.get(f), str) and sq[f].strip() for f in ('search_query','ranking_query'))."],"exampleFix":"# before\n{\"search_query\": \"zig vs rust\", \"sources\": [\"reddit\"]}\n\n# after\n{\"search_query\": \"zig vs rust\", \"ranking_query\": \"zig vs rust performance\", \"sources\": [\"reddit\"]}","handlingStrategy":"validation","validationCode":"for i, q in enumerate(plan[\"subqueries\"]):\n    for f in (\"search_query\", \"ranking_query\"):\n        v = q.get(f)\n        if not isinstance(v, str) or not v.strip():\n            q[f] = q.get(\"search_query\", \"\") or q.get(\"ranking_query\", \"\")  # mirror the other field\n            if not q[f].strip():\n                raise SystemExit(f\"subqueries[{i}] lacks usable queries\")","typeGuard":"def has_query_pair(q: dict) -> bool:\n    return all(isinstance(q.get(f), str) and q[f].strip() for f in (\"search_query\", \"ranking_query\"))","tryCatchPattern":null,"preventionTips":["Default ranking_query to search_query when no separate ranking terms exist.","Lint generated plans for both fields before submission."],"tags":["planner","external-plan","validation","json"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}