{"record":{"id":"445d3ff1c1094327","repo":"shareAI-lab/learn-claude-code","slug":"task-file-id-does-not-match-task-id","errorCode":null,"errorMessage":"Task file ID does not match {task_id}","messagePattern":"Task file ID does not match (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"s10_task_system/code.py","lineNumber":141,"sourceCode":"                    \"x\", encoding=\"utf-8\"\n                ) as handle:\n                    json.dump(asdict(task), handle, indent=2)\n                return task\n            except FileExistsError:\n                continue\n        raise RuntimeError(\"Could not allocate a unique task ID\")\n\n    def save(self, task: Task) -> None:\n        self._path(task.id, create_root=True).write_text(\n            json.dumps(asdict(task), indent=2),\n            encoding=\"utf-8\",\n        )\n\n    def load(self, task_id: str) -> Task:\n        data = json.loads(self._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    def list(self) -> list[Task]:\n        if not self.directory.exists():\n            return []\n        root = self._root()\n        return [self.load(path.stem)\n                for path in sorted(root.glob(\"task_*.json\"))]\n\n\nTASKS = TaskStore(TASKS_DIR)\n\n\ndef create_task(subject: str, description: str = \"\",\n                blockedBy: list[str] | None = None) -> Task:\n    return TASKS.create(subject, description, blockedBy)","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s10_task_system/code.py#L123-L159","documentation":"Raised by TaskStore.load() in s10_task_system/code.py:141 when the JSON file at {task_id}.json parses and constructs a Task, but the Task's own id field differs from the task_id used to locate the file. The filename and the embedded id must agree; a mismatch means the file was renamed, hand-edited, or copied from another task. The check runs before the status check, and save() always writes a matching pair, so mismatched files come from external modification.","triggerScenarios":"Renaming .tasks/task_aaaa1111.json to task_bbbb2222.json and calling load('task_bbbb2222'); editing the JSON in a text editor and changing the id field; copying a task file as a template and forgetting to update both the filename and the id; merging stores by hand.","commonSituations":"Manual 'duplicate this task' workflows done in the file manager; version-control conflicts resolved by keeping one file under another's name; migration scripts that rewrite ids but not filenames (or vice versa).","solutions":["Restore agreement: either rename the file back to {task.id}.json or edit the JSON's id to equal the filename's stem.","Duplicate tasks via store.create() + save(task with replace(id=...)) rather than by copying files.","In migration scripts, always write both the filename and the embedded id from the same source."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import json\nfrom pathlib import Path\n\ndef file_matches_id(store_dir: Path, task_id: str) -> bool:\n    p = store_dir / f'{task_id}.json'\n    if not p.is_file():\n        return False\n    return json.loads(p.read_text()).get('id') == task_id","typeGuard":null,"tryCatchPattern":"try:\n    task = store.load(task_id)\nexcept ValueError as e:\n    if 'does not match' in str(e):\n        # heal: rewrite the embedded id, or rename the file\n        heal_task_file(store.directory, task_id)\n        task = store.load(task_id)\n    else:\n        raise","preventionTips":["Duplicate tasks via create()+save(), never by copying files.","In migrations, write filename and embedded id from the same value.","Reject manual edits to .tasks/*.json in project tooling; use the API."],"tags":["tasks","data-integrity","json","ids"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}