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
- Use exactly "pending", "in_progress", or "completed" — lowercase, underscore
- Lowercase and strip status strings at the call site if the value comes from free text
- 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
- This check is case-sensitive: lower/strip status before the call
- Map 'done' -> 'completed' at the call site
- Model blocked/cancelled via blockedBy lists, not via status
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
- Invalid status: {status}
- Item {item_id}: invalid status '{status}'
- Only one task can be in_progress at a time
- Task {task_id} not found
- Task {task_id} not found
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/4e0df4fac1084cc5.
Report an issue: GitHub.