Skip to content

[BUG] Todo tools silently fail on numeric-looking ids (e.g. "1e5230" parsed to inf) #670

Description

@sean-kim05

Component

strix/tools/todo/tools.py_normalize_todo_ids

Environment

  • Strix version: main (302efed)
  • Python / OS: deterministic pure-logic bug; reproducible on any Python 3.12+ and any OS
  • LLM: N/A (no model involved to reproduce)
  • Traceback: N/A — no exception; the tool returns "Todo with ID 'inf' not found" and silently no-ops on the real todo

Description

_normalize_todo_ids accepts a JSON array, a comma-separated string, or a single bare id. It runs the input through json.loads and, when the parsed value isn't a list, returns str(parsed):

try:
    data = json.loads(stripped)
except json.JSONDecodeError:
    data = stripped.split(",") if "," in stripped else [stripped]
if isinstance(data, list):
    return [str(item).strip() for item in data if str(item).strip()]
return [str(data).strip()]        # <-- str() of a parsed JSON scalar

Todo ids are generated as str(uuid.uuid4())[:6] — 6-char hex slugs. Slugs like 1e5230, 2363e0, 0e4440 are valid JSON numbers:

  • json.loads("1e5230")float('inf')"inf"
  • json.loads("2363e0")2363.0"2363.0"

So mark_todo_done, mark_todo_pending, and delete_todo operate on the wrong (non-existent) id whenever such an id is passed as a bare string — a form the comma/split fallback explicitly supports.

Steps to reproduce

from strix.tools.todo.tools import _normalize_todo_ids
_normalize_todo_ids("1e5230")   # a real 6-char uuid slug

Or end-to-end: create a todo whose id is 1e5230, then call mark_todo_done(todo_ids="1e5230") (bare string, not wrapped in an array).

Expected

["1e5230"]; the referenced todo is marked done.

Actual

["inf"]; the tool reports Todo with ID 'inf' not found and the real todo is left untouched.

Proposed fix

#663 — use json.loads only to detect the JSON array form; treat any non-array input as a literal id (optionally comma-separated).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions