{"record":{"id":"1867fb52d4699329","repo":"shareAI-lab/learn-claude-code","slug":"invalid-task-status-task-status-1867fb","errorCode":null,"errorMessage":"Invalid task status: {task.status}","messagePattern":"Invalid task status: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"s15_integrated_harness/code.py","lineNumber":258,"sourceCode":"            f\".{path.name}.{os.getpid()}.{threading.get_ident()}.tmp\"\n        )\n        try:\n            temporary.write_text(\n                json.dumps(asdict(task), indent=2), encoding=\"utf-8\"\n            )\n            os.replace(temporary, path)\n        finally:\n            temporary.unlink(missing_ok=True)\n\n\ndef load_task(task_id: str) -> Task:\n    with task_lock:\n        data = json.loads(_task_path(task_id).read_text(encoding=\"utf-8\"))\n        task = Task(**data)\n        if task.id != task_id:\n            raise ValueError(f\"Task file ID does not match {task_id}\")\n        if task.status not in {\"pending\", \"in_progress\", \"completed\"}:\n            raise ValueError(f\"Invalid task status: {task.status}\")\n        return task\n\n\ndef list_tasks() -> list[Task]:\n    with task_lock:\n        if not TASKS_DIR.exists():\n            return []\n        if not TASKS_ROOT.is_relative_to(WORKDIR.resolve()):\n            raise ValueError(\"Tasks directory escapes workspace\")\n        return [load_task(path.stem)\n                for path in sorted(TASKS_DIR.glob(\"task_*.json\"))]\n\n\ndef get_task_json(task_id: str) -> str:\n    return json.dumps(asdict(load_task(task_id)), indent=2)\n\n\ndef can_start(task_id: str) -> bool:","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s15_integrated_harness/code.py#L240-L276","documentation":"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.","triggerScenarios":"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.","commonSituations":"Manual edits 'marking a task done'; scripts migrating tasks from another tracker that uses different status names; version drift after the status enum changed.","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."],"exampleFix":"// before\n{\"id\": \"task_0a1b2c3d\", \"status\": \"done\", ...}\n\n// after\n{\"id\": \"task_0a1b2c3d\", \"status\": \"completed\", ...}","handlingStrategy":"validation","validationCode":"VALID_STATUSES = {\"pending\", \"in_progress\", \"completed\"}\n\ndef has_valid_status(task: dict) -> bool:\n    return task.get(\"status\") in VALID_STATUSES","typeGuard":"def is_task_status(value) -> bool:\n    return value in {\"pending\", \"in_progress\", \"completed\"}","tryCatchPattern":"try:\n    task = load_task(task_id)\nexcept ValueError as e:\n    if \"Invalid task status\" in str(e):\n        # rewrite the file's status to a canonical value or quarantine it\n        raise","preventionTips":["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."],"tags":["task","status","data-integrity","validation"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}