shareAI-lab/learn-claude-code · error · ValueError
Invalid task status: {task.status}
Error message
Invalid task status: {task.status} What it means
load_task() enforces a closed status vocabulary: {'pending', 'in_progress', 'completed'}. The Task dataclass annotates status as a bare str, so any other string (or a status written by a newer/older version) is rejected at load time rather than silently flowing into scheduling logic.
Source
Thrown at s13_agent_teams/code.py:183
f".{path.name}.{os.getpid()}.{threading.get_ident()}.tmp"
)
try:
temporary.write_text(
json.dumps(asdict(task), indent=2), encoding="utf-8"
)
os.replace(temporary, path)
finally:
temporary.unlink(missing_ok=True)
def load_task(task_id: str) -> Task:
with task_lock:
data = json.loads(_task_path(task_id).read_text(encoding="utf-8"))
task = Task(**data)
if task.id != task_id:
raise ValueError(f"Task file ID does not match {task_id}")
if task.status not in {"pending", "in_progress", "completed"}:
raise ValueError(f"Invalid task status: {task.status}")
return task
def list_tasks() -> list[Task]:
with task_lock:
if not TASKS_DIR.exists():
return []
if not TASKS_ROOT.is_relative_to(WORKDIR.resolve()):
raise ValueError("Tasks directory escapes workspace")
return [load_task(path.stem)
for path in sorted(TASKS_DIR.glob("task_*.json"))]
def get_task(task_id: str) -> str:
"""Return full task details as JSON."""
task = load_task(task_id)
return json.dumps(asdict(task), indent=2)
View on GitHub (pinned to 985456f4ad)
Solutions
- Use exactly one of 'pending', 'in_progress', 'completed' (lowercase, underscore).
- Update test fixtures and scripts that write informal statuses like 'done'.
- If a new status is genuinely needed, add it to the set in load_task() everywhere the vocabulary is checked.
Example fix
// before save_task(replace_status(task, 'done')) // next load_task raises // after save_task(replace_status(task, 'completed'))
Defensive patterns
Strategy: validation
Validate before calling
VALID_STATUSES = {'pending', 'in_progress', 'completed'}
def valid_status(status: object) -> bool:
return status in VALID_STATUSES Type guard
from typing import Literal, TypeGuard
TaskStatus = Literal['pending', 'in_progress', 'completed']
def is_task_status(value: object) -> TypeGuard[TaskStatus]:
return value in {'pending', 'in_progress', 'completed'} Try / catch
try:
task = load_task(task_id)
except ValueError as exc:
if 'Invalid task status' in str(exc):
log_and_quarantine(task_id) # move file aside for inspection
return None
raise Prevention
- Use the literal strings 'pending' | 'in_progress' | 'completed'.
- Type status as Literal[...] in your own code so typos fail statically.
- Validate fixture files' status values in tests.
When it happens
Trigger: Hand-editing .tasks/*.json to 'done', 'Done', 'in-progress' (hyphen), or 'blocked'; a newer version of the system writing a new status like 'failed' that this version doesn't know; serializing an enum instead of its value.
Common situations: Manual status edits; version skew between components sharing the .tasks directory; test fixtures written with informal status names.
Related errors
- Invalid task status: {task.status}
- Invalid task status: {task.status}
- Task file ID does not match {task_id}
- Max 20 todos allowed
- Item {item_id}: text required
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/4df1c40c7f44ba9b.
Report an issue: GitHub.