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

  1. Use one of: low, normal, high, critical (case-insensitive, surrounding whitespace is fine).
  2. Map foreign vocabularies before calling: medium->normal, urgent/critical->critical, low/minor->low.
  3. 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

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


AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15). Data as JSON: /api/errors/9a9f8cfead2381c8. Report an issue: GitHub.