{"record":{"id":"14de6dd5eabe3661","repo":"shareAI-lab/learn-claude-code","slug":"task-task-id-not-found","errorCode":null,"errorMessage":"Task {task_id} not found","messagePattern":"Task (.+?) not found","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agents/s07_task_system.py","lineNumber":60,"sourceCode":"\nSYSTEM = f\"You are a coding agent at {WORKDIR}. Use task tools to plan and track work.\"\n\n\n# -- TaskManager: CRUD with dependency graph, persisted as JSON files --\nclass TaskManager:\n    def __init__(self, tasks_dir: Path):\n        self.dir = tasks_dir\n        self.dir.mkdir(exist_ok=True)\n        self._next_id = self._max_id() + 1\n\n    def _max_id(self) -> int:\n        ids = [int(f.stem.split(\"_\")[1]) for f in self.dir.glob(\"task_*.json\")]\n        return max(ids) if ids else 0\n\n    def _load(self, task_id: int) -> dict:\n        path = self.dir / f\"task_{task_id}.json\"\n        if not path.exists():\n            raise ValueError(f\"Task {task_id} not found\")\n        return json.loads(path.read_text())\n\n    def _save(self, task: dict):\n        path = self.dir / f\"task_{task['id']}.json\"\n        path.write_text(json.dumps(task, indent=2, ensure_ascii=False))\n\n    def create(self, subject: str, description: str = \"\") -> str:\n        task = {\n            \"id\": self._next_id, \"subject\": subject, \"description\": description,\n            \"status\": \"pending\", \"blockedBy\": [], \"owner\": \"\",\n        }\n        self._save(task)\n        self._next_id += 1\n        return json.dumps(task, indent=2, ensure_ascii=False)\n\n    def get(self, task_id: int) -> str:\n        return json.dumps(self._load(task_id), indent=2, ensure_ascii=False)\n","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/agents/s07_task_system.py#L42-L78","documentation":"Raised by TaskManager._load() in agents/s07_task_system.py:60 when a task JSON file for the given id does not exist under tasks_dir. Ids map 1:1 to files task_<id>.json; _max_id() bootstraps the next id from existing filenames at startup, so any get/update/remove call with an id that was never created — or whose file was deleted externally — fails here.","triggerScenarios":"Calling task_get/task_update with a guessed or stale id (e.g. after the tasks dir was wiped between runs, so old ids no longer exist), a deleted task, or an id larger than the max seen by list_tasks(). Note _max_id() does int(f.stem.split(\"_\")[1]) without a try/except here, so a manually created task file with a non-numeric suffix would crash earlier at startup rather than here.","commonSituations":"Agent resumes a session with persisted conversation but a cleaned tasks dir. Model hallucinates an id instead of calling task_list first. Two harness instances sharing one tasks_dir racing on file deletion.","solutions":["Call task_list/task_next first and use ids from its output, never guessed ids","After wiping or moving the tasks dir, restart the conversation or re-create tasks — old ids are invalid","Treat this error as terminal for that id: do not retry the same id; pick an existing one"],"exampleFix":"# before\ntasks.update(task_id=7, status=\"in_progress\")\n# ValueError: Task 7 not found\n\n# after\nexisting = json.loads(tasks.list())\nids = [t[\"id\"] for t in existing if t[\"status\"] == \"pending\"]\nif ids:\n    tasks.update(task_id=ids[0], status=\"in_progress\")","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef task_exists(tasks_dir: Path, task_id: int) -> bool:\n    return (tasks_dir / f\"task_{task_id}.json\").exists()\n\n# before get/update:\nassert task_exists(TASKS_DIR, task_id), f\"Task {task_id} not found; call task_list for valid ids\"","typeGuard":"def is_valid_task_id(task_id: object, tasks_dir) -> bool:\n    if not isinstance(task_id, int) or isinstance(task_id, bool) or task_id < 1:\n        return False\n    return (tasks_dir / f\"task_{task_id}.json\").exists()","tryCatchPattern":"try:\n    TASKS.update(task_id, status)\nexcept ValueError as e:\n    if \"not found\" in str(e):\n        valid = TASKS.list()\n        return f\"Task {task_id} no longer exists. Current tasks:\\n{valid}\"\n    raise","preventionTips":["Always call task_list first and use ids from its output","Never guess or extrapolate ids; they are file-backed, not generated","If you wipe the tasks dir, invalidate every id held in conversation/memory"],"tags":["validation","task-system","persistence","python"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}