{"record":{"id":"fed621f3632401aa","repo":"shareAI-lab/learn-claude-code","slug":"assignment-cwd-changed-for-task-task-id-fed621","errorCode":null,"errorMessage":"Assignment cwd changed for task {task.id}","messagePattern":"Assignment cwd changed for task (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"s15_integrated_harness/code.py","lineNumber":482,"sourceCode":"    with task_lock:\n        assignment = teammate_assignments.get(owner)\n        task = _owner_in_progress(owner)\n        if task and (not assignment or assignment.get(\"task_id\") != task.id):\n            cwd, error = task_worktree_cwd(task)\n            if error:\n                raise ValueError(error)\n            assignment = {\"task_id\": task.id, \"cwd\": cwd}\n            teammate_assignments[owner] = assignment\n        elif not assignment:\n            return WORKDIR\n        task = load_task(str(assignment[\"task_id\"]))\n        if task.status not in {\"in_progress\", \"completed\"} or task.owner != owner:\n            raise ValueError(f\"Assignment for {owner} is no longer active\")\n        cwd, error = task_worktree_cwd(task)\n        if error:\n            raise ValueError(error)\n        if cwd.resolve() != Path(assignment[\"cwd\"]).resolve():\n            raise ValueError(f\"Assignment cwd changed for task {task.id}\")\n        return cwd\n\n\ndef release_completed_assignment(owner: str) -> bool:\n    \"\"\"Release a completed cwd lease only at a model turn boundary.\"\"\"\n    with task_lock:\n        assignment = teammate_assignments.get(owner)\n        if not assignment:\n            return False\n        task = load_task(str(assignment[\"task_id\"]))\n        if task.status != \"completed\" or task.owner != owner:\n            return False\n        teammate_assignments.pop(owner, None)\n        advance_assignment_version(owner)\n        if owner in globals().get(\"plan_gates\", {}):\n            globals()[\"plan_gates\"][owner] = \"not_required\"\n        return True\n","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s15_integrated_harness/code.py#L464-L500","documentation":"After confirming an assignment's task is active, the harness recomputes the task's worktree cwd and compares it (resolved) to the cwd recorded when the lease was granted. A mismatch means the on-disk worktree location for that task changed under the lease — e.g. the worktree was recreated at a different path, or the recorded cwd pointed at a since-moved directory. Continuing would run commands in the wrong directory, so it aborts.","triggerScenarios":"Deleting and recreating a task's worktree under a different name/path while its owner holds a lease; task.worktree field edited between turns; WORKTREES_DIR restructured; the recorded absolute cwd became stale after moving the whole workspace.","commonSituations":"Agents running 'git worktree prune/remove + add' on an in-use worktree; moving or cloning the workspace to a new path without restarting sessions; hand-editing task JSON's worktree field.","solutions":["Do not remove/recreate a worktree while its task is in_progress; finish or reassign the task first.","Restart the harness after moving the workspace so absolute cwds in assignments are regenerated.","Change a task's worktree only through the harness APIs so the lease updates atomically."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"from pathlib import Path\n\ndef worktree_stable(task, recorded_cwd: str) -> bool:\n    cwd, err = task_worktree_cwd(task)\n    if err:\n        return False\n    return cwd.resolve() == Path(recorded_cwd).resolve()","typeGuard":null,"tryCatchPattern":"try:\n    cwd = _agent_cwd_for(owner)\nexcept ValueError as e:\n    if \"cwd changed\" in str(e):\n        # worktree was moved/recreated: re-establish the lease via restart\n        raise","preventionTips":["Never prune/recreate a worktree whose task is in_progress.","Restart the harness after relocating the workspace.","Change worktree bindings only through harness APIs."],"tags":["worktree","stale-state","session","concurrency"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}