mvanhorn/last30days-skill · error · ValueError
subqueries[{index}] must be an object
Error message
subqueries[{index}] must be an object What it means
Per-item check in validate_external_plan: each element of subqueries must itself be a dict/object. A bare string query, null entry, or nested list fails with the offending index in the message, making it easy to locate the bad element.
Source
Thrown at skills/last30days/scripts/lib/planner.py:194
raise ValueError(f"field '{field}' must be a non-empty string")
source_weights = raw.get("source_weights")
if source_weights is not None and not isinstance(source_weights, dict):
raise ValueError("field 'source_weights' must be an object when provided")
for source, weight in (source_weights or {}).items():
if (
not isinstance(source, str)
or not source.strip()
or isinstance(weight, bool)
or not isinstance(weight, (int, float))
):
raise ValueError("field 'source_weights' must map source names to numbers")
subqueries = raw["subqueries"]
if not isinstance(subqueries, list) or not subqueries:
raise ValueError("field 'subqueries' must be a non-empty array")
for index, subquery in enumerate(subqueries):
if not isinstance(subquery, dict):
raise ValueError(f"subqueries[{index}] must be an object")
for field in ("search_query", "ranking_query"):
if not isinstance(subquery.get(field), str) or not subquery[field].strip():
raise ValueError(f"subqueries[{index}].{field} must be a non-empty string")
sources = subquery.get("sources")
if not isinstance(sources, list) or not sources or not all(
isinstance(source, str) and source.strip() for source in sources
):
raise ValueError(f"subqueries[{index}].sources must be a non-empty string array")
weight = subquery.get("weight")
if weight is not None and (
isinstance(weight, bool) or not isinstance(weight, (int, float))
):
raise ValueError(f"subqueries[{index}].weight must be a number when provided")
DEFAULT_INTENT_CAPABILITIES = {
"comparison": {"discussion", "video", "web", "reference", "social", "link", "market"},
"how_to": {"discussion", "video", "web", "reference", "link"},View on GitHub (pinned to c7460f6114)
Solutions
- Wrap bare strings into objects: {"search_query": s, "ranking_query": s, "sources": ["reddit"]}.
- Filter out None entries before submission: [q for q in subqueries if q].
- Check the index named in the error message first.
Example fix
# before
"subqueries": ["rust compilers 2026"]
# after
"subqueries": [{"search_query": "rust compilers 2026", "ranking_query": "rust compiler release", "sources": ["reddit"]}] Defensive patterns
Strategy: validation
Validate before calling
plan["subqueries"] = [q for q in plan["subqueries"] if isinstance(q, dict)]
if not plan["subqueries"]:
raise SystemExit("no valid subquery objects after filtering") Type guard
def is_subquery_object(v) -> bool:
return isinstance(v, dict) Prevention
- Normalize bare-string subqueries to full objects at the emitting side.
- Use the index from the error message to find the bad element fast.
When it happens
Trigger: "subqueries": ["rust compilers", {...}] — the first element is a string, not an object; or a null element from a generator that skipped an item.
Common situations: LLMs sometimes emit shorthand string queries instead of full objects; list filtering leaves None placeholders; copy-paste of a query string into the array.
Related errors
- top-level plan must be an object
- missing required field '{field}'
- field '{field}' must be a non-empty string
- field 'source_weights' must be an object when provided
- field 'source_weights' must map source names to numbers
AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15).
Data as JSON: /api/errors/a0465c3dbf36da72.
Report an issue: GitHub.