shareAI-lab/learn-claude-code · error · ValueError

Invalid status: {status}

Error message

Invalid status: {status}

What it means

Raised by TaskManager.update() in agents/s07_task_system.py:84 when the `status` argument is truthy but not one of "pending", "in_progress", "completed". Like the todo manager, the task store is a closed status set; on success, transitioning to "completed" also clears the task from every other task's blockedBy via _clear_dependency().

Source

Thrown at agents/s07_task_system.py:84

    def create(self, subject: str, description: str = "") -> str:
        task = {
            "id": self._next_id, "subject": subject, "description": description,
            "status": "pending", "blockedBy": [], "owner": "",
        }
        self._save(task)
        self._next_id += 1
        return json.dumps(task, indent=2, ensure_ascii=False)

    def get(self, task_id: int) -> str:
        return json.dumps(self._load(task_id), indent=2, ensure_ascii=False)

    def update(self, task_id: int, status: str = None,
               add_blocked_by: list = None, remove_blocked_by: list = None) -> str:
        task = self._load(task_id)
        if status:
            if status not in ("pending", "in_progress", "completed"):
                raise ValueError(f"Invalid status: {status}")
            task["status"] = status
            if status == "completed":
                self._clear_dependency(task_id)
        if add_blocked_by:
            task["blockedBy"] = list(set(task["blockedBy"] + add_blocked_by))
        if remove_blocked_by:
            task["blockedBy"] = [x for x in task["blockedBy"] if x not in remove_blocked_by]
        self._save(task)
        return json.dumps(task, indent=2, ensure_ascii=False)

    def _clear_dependency(self, completed_id: int):
        """Remove completed_id from all other tasks' blockedBy lists."""
        for f in self.dir.glob("task_*.json"):
            task = json.loads(f.read_text())
            if completed_id in task.get("blockedBy", []):
                task["blockedBy"].remove(completed_id)
                self._save(task)

View on GitHub (pinned to 985456f4ad)

Solutions

  1. Use exactly "pending", "in_progress", or "completed" — lowercase, underscore
  2. Lowercase and strip status strings at the call site if the value comes from free text
  3. Remember blocked/cancelled states are not modeled: remove blockers via remove_blocked_by instead of inventing a status

Example fix

# before
tasks.update(task_id=3, status="Done")
# ValueError: Invalid status: Done

# after
tasks.update(task_id=3, status="completed")
Defensive patterns

Strategy: validation

Validate before calling

VALID = {"pending", "in_progress", "completed"}
status = (status or "").strip().lower() or None
assert status is None or status in VALID, f"Invalid status: {status}; use one of {sorted(VALID)}"

Type guard

TASK_STATUSES = frozenset(("pending", "in_progress", "completed"))

def is_valid_task_status(s: object) -> bool:
    return s is None or (isinstance(s, str) and s in TASK_STATUSES)  # note: case-sensitive

Try / catch

try:
    TASKS.update(task_id, status)
except ValueError as e:
    if "Invalid status" in str(e):
        return f"Tool error: {e}. Allowed: pending, in_progress, completed (exact lowercase)."
    raise

Prevention

When it happens

Trigger: Calling task_update with status="done", "blocked", "cancelled", "In Progress" (capitalized variants fail too — no lowercasing here, unlike the todo manager), or an empty-ish-but-truthy string.

Common situations: Models defaulting to "done". Code that passes a user-facing status string straight through. Note the asymmetry with s03: this file does not normalize case, so "Completed" fails.

Related errors


AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14). Data as JSON: /api/errors/4e0df4fac1084cc5. Report an issue: GitHub.