{"record":{"id":"7acfd155f40f80a7","repo":"shareAI-lab/learn-claude-code","slug":"task-file-id-does-not-match-task-id-7acfd1","errorCode":null,"errorMessage":"Task file ID does not match {task_id}","messagePattern":"Task file ID does not match (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"s15_integrated_harness/code.py","lineNumber":256,"sourceCode":"        path = _task_path(task.id)\n        temporary = path.with_name(\n            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","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s15_integrated_harness/code.py#L238-L274","documentation":"load_task() reads <task_id>.json, deserializes it into a Task, and verifies the JSON's internal 'id' field equals the filename stem. A mismatch means the file was renamed, hand-edited, or copied without updating its contents — the store's filename/content invariant is broken, so the record is rejected rather than silently returned.","triggerScenarios":"Manually renaming a task_*.json file; copying a task file to a new name as a 'duplicate'; editing the JSON's id field by hand; a buggy external script rewriting task files.","commonSituations":"Developers cloning a task by cp task_a.json task_b.json; sed-based bulk edits of task files; manual 'fixes' to the tasks directory outside the API.","solutions":["Never rename or copy task files by hand — use create_task() and update via save_task().","If a file was renamed, update its internal \"id\" field to match the new filename stem.","Delete the corrupted file and recreate the task through the API."],"exampleFix":"// before (shell)\n$ cp .tasks/task_0a1b2c3d.json .tasks/task_9f8e7d6c.json\n\n// after (python)\nnew = create_task(orig.subject, orig.description, blockedBy=orig.blockedBy)","handlingStrategy":"validation","validationCode":"import json\nfrom pathlib import Path\n\ndef task_file_consistent(p: Path) -> bool:\n    try:\n        return json.loads(p.read_text())[\"id\"] == p.stem\n    except Exception:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    task = load_task(task_id)\nexcept ValueError as e:\n    if \"ID does not match\" in str(e):\n        # file renamed/hand-edited: reconcile id field with filename or recreate\n        raise","preventionTips":["Never rename/cp task files manually.","Mutate tasks only through save_task()/APIs.","Run a consistency sweep (id == filename stem) after any bulk migration."],"tags":["task","data-integrity","filesystem"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}