usestrix/strix · error · ValueError
Each todo entry must include a non-empty 'title'
Error message
Each todo entry must include a non-empty 'title'
What it means
Thrown when a dict-shaped todo entry has a 'title' that is missing, not a string, or blank after stripping. The title is the only required field per entry; description and priority are optional. Empty string entries from bare strings are silently skipped, but dict entries with empty titles are hard errors.
Source
Thrown at strix/tools/todo/tools.py:220
return [{"title": entry} for entry in entries]
if isinstance(data, dict):
data = [data]
if not isinstance(data, list):
raise TypeError("Todos must be provided as a list, dict, or JSON string")
normalized: list[dict[str, Any]] = []
for item in data:
if isinstance(item, str):
title = item.strip()
if title:
normalized.append({"title": title})
continue
if not isinstance(item, dict):
raise TypeError("Each todo entry must be a string or object with a title")
title = item.get("title", "")
if not isinstance(title, str) or not title.strip():
raise ValueError("Each todo entry must include a non-empty 'title'")
normalized.append(
{
"title": title.strip(),
"description": (item.get("description") or "").strip() or None,
"priority": item.get("priority"),
},
)
return normalized
def _apply_single_update(
agent_todos: dict[str, dict[str, Any]],
todo_id: str,
title: str | None = None,
description: str | None = None,
priority: str | None = None,
status: str | None = None,
) -> dict[str, Any] | None:View on GitHub (pinned to 8551339130)
Solutions
- Give every todo object a non-empty string 'title': {'title': 'write tests', 'description': '...'}
- If the text landed in 'description', move it to 'title'
- Strip whitespace when generating titles programmatically and skip blanks
Example fix
# before
todos = [{"description": "refactor auth module"}]
# after
todos = [{"title": "refactor auth module"}] Defensive patterns
Strategy: validation
Validate before calling
for t in todos:
if isinstance(t, dict):
title = t.get("title")
assert isinstance(title, str) and title.strip(), f"bad title in {t!r}" Type guard
def has_valid_title(t) -> bool:
if isinstance(t, str):
return bool(t.strip())
return isinstance(t, dict) and isinstance(t.get("title"), str) and bool(t["title"].strip()) Try / catch
try:
tool.write_todos(todos)
except ValueError as e:
if "title" in str(e):
todos = [t if isinstance(t, str) else {**t, "title": t.get("title") or t.get("description") or "untitled"} for t in todos]
tool.write_todos(todos) Prevention
- Fall back description -> title when preparing payloads
- Trim and skip blank titles during generation instead of letting the tool reject them
When it happens
Trigger: todos=[{'description': 'no title'}], todos=[{'title': ''}], todos=[{'title': 42}] (non-string title), or a title of only whitespace.
Common situations: Agent moving the task text into 'description' and leaving 'title' empty; templating that renders an unset variable as ''; numbers or ids mistakenly placed in title.
Related errors
- Each update must include 'todo_id'
- Todos must be provided as a list, dict, or JSON string
- Each todo entry must be a string or object with a title
- extra_system_prompt_context cannot override built-in scope k
- Cannot resume scan {scan_id}: agents.json has no root agent
AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15).
Data as JSON: /api/errors/a9705698e27a7270.
Report an issue: GitHub.