usestrix/strix · warning · ValueError
Invalid priority. Must be one of: {', '.join(VALID_PRIORITIE
Error message
Invalid priority. Must be one of: {', '.join(VALID_PRIORITIES)} What it means
The todo tool normalizes priority strings: strip + lower, then membership check against VALID_PRIORITIES = ['low', 'normal', 'high', 'critical'] (strix/tools/todo/tools.py:20). Any other value raises ValueError listing the allowed set. _normalize_priority is the strict path; _coerce_priority wraps it to fall back to the default.
Source
Thrown at strix/tools/todo/tools.py:115
tmp_path = Path(tmp.name)
tmp_path.replace(path)
except Exception:
logger.exception("todos persist to %s failed", path)
def _agent_id_from(ctx: RunContextWrapper) -> str:
inner = ctx.context if isinstance(ctx.context, dict) else {}
return str(inner.get("agent_id") or "default")
def _get_agent_todos(agent_id: str) -> dict[str, dict[str, Any]]:
return _todos_storage.setdefault(agent_id, {})
def _normalize_priority(priority: str | None, default: str = "normal") -> str:
candidate = str(priority or default or "normal").strip().lower()
if candidate not in VALID_PRIORITIES:
raise ValueError(f"Invalid priority. Must be one of: {', '.join(VALID_PRIORITIES)}")
return candidate
def _coerce_priority(priority: str | None, default: str = "normal") -> str:
try:
return _normalize_priority(priority, default)
except ValueError:
return default
def _sorted_todos(agent_id: str) -> list[dict[str, Any]]:
todos_list = [
{**todo, "todo_id": todo_id} for todo_id, todo in _get_agent_todos(agent_id).items()
]
todos_list.sort(key=_todo_sort_key)
return todos_list
View on GitHub (pinned to 8551339130)
Solutions
- Use one of: low, normal, high, critical (case-insensitive, surrounding whitespace is fine).
- Map foreign vocabularies before calling: medium->normal, urgent/critical->critical, low/minor->low.
- If you want lenient behavior, route through _coerce_priority so invalid values fall back to the default instead of raising.
Example fix
# before update_todo(todo_id="t1", priority="medium") # raises # after update_todo(todo_id="t1", priority="normal") # or "low"|"high"|"critical"
Defensive patterns
Strategy: validation
Validate before calling
from strix.tools.todo.tools import VALID_PRIORITIES
def normalize_priority(p: str | None) -> str:
p = (p or "normal").strip().lower()
return p if p in VALID_PRIORITIES else "normal" Type guard
from typing import Literal
Priority = Literal["low", "normal", "high", "critical"]
def is_priority(v: object) -> bool:
return isinstance(v, str) and v.strip().lower() in {"low", "normal", "high", "critical"} Try / catch
try:
add_todo(title=t, priority=p)
except ValueError as exc:
if "Invalid priority" in str(exc):
p = {"medium": "normal", "urgent": "high"}.get(p.lower(), "normal")
add_todo(title=t, priority=p)
else:
raise Prevention
- Map foreign vocabularies (medium->normal) at your boundary before calling todo tools.
- Use _coerce_priority when you want lenient defaulting instead of a raise.
- Constrain LLM tool args to the four valid values via enum schema.
When it happens
Trigger: Calling a todo tool function that validates strictly (via _normalize_priority) with priority='urgent', 'P1', 'Normal ' works (case/space tolerant) but 'medium' or 'sev1' fails. Passing None falls back to the default and does not raise.
Common situations: LLM agents using their own priority vocabulary ('medium' is the classic collision); mixing todo schemas from other tools (Jira/GitHub labels); upstream enum extended without updating callers.
Related errors
- Updates must be valid JSON
- Unknown action: {action}
- Failed to calculate CVSS for validated vector: {vector}
- Updates must be a list of update objects
- Each update must be an object with todo_id
AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15).
Data as JSON: /api/errors/9a9f8cfead2381c8.
Report an issue: GitHub.