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 set of statuses: pending, in_progress, completed. Any other value in the JSON file is rejected because downstream logic (can_start, assignment leasing, completion release) switches on exactly these states; an unknown status would make scheduling undefined.
Source
Thrown at s15_integrated_harness/code.py:258
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_json(task_id: str) -> str:
return json.dumps(asdict(load_task(task_id)), indent=2)
def can_start(task_id: str) -> bool:View on GitHub (pinned to 985456f4ad)
Solutions
- Use only the three canonical statuses; transition tasks via the harness's claim/complete APIs, not file edits.
- If migrating, map external statuses onto {pending, in_progress, completed} before writing.
- Fix any offending files in TASKS_DIR with a one-off script that rewrites non-canonical statuses.
Example fix
// before
{"id": "task_0a1b2c3d", "status": "done", ...}
// after
{"id": "task_0a1b2c3d", "status": "completed", ...} Defensive patterns
Strategy: validation
Validate before calling
VALID_STATUSES = {"pending", "in_progress", "completed"}
def has_valid_status(task: dict) -> bool:
return task.get("status") in VALID_STATUSES Type guard
def is_task_status(value) -> bool:
return value in {"pending", "in_progress", "completed"} Try / catch
try:
task = load_task(task_id)
except ValueError as e:
if "Invalid task status" in str(e):
# rewrite the file's status to a canonical value or quarantine it
raise Prevention
- Map external tracker statuses to the three canonical values during migration.
- Never hand-edit status fields.
- Add a lint check over TASKS_DIR after bulk edits.
When it happens
Trigger: A task JSON containing "status": "done", "blocked", "failed", capitalized variants, or a typo; hand-edited files; a writer from an older/newer version of the harness with a different status vocabulary.
Common situations: Manual edits 'marking a task done'; scripts migrating tasks from another tracker that uses different status names; version drift after the status enum changed.
Related errors
- Invalid task status: {task.status}
- Invalid task status: {task.status}
- Task subject cannot be empty
- Dependency not found: {dependency}
- Task file ID does not match {task_id}
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/1867fb52d4699329.
Report an issue: GitHub.