{"record":{"id":"6a7f8dbc71c76074","repo":"gitbutlerapp/gitbutler","slug":"some-selected-changes-no-longer-match-the-worktree-s","errorCode":null,"errorMessage":"Some selected changes no longer match the worktree's uncommitted changes: {}","messagePattern":"Some selected changes no longer match the worktree's uncommitted changes: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/worktrees.rs","lineNumber":203,"sourceCode":"            worktree_repo.create_wd_tree(0)?\n        }\n        Some(selection) => {\n            if selection.is_empty() {\n                bail!(\"No changes were selected to move\");\n            }\n            let outcome = but_core::tree::create_tree(\n                worktree_repo,\n                worktree_head_tree,\n                selection,\n                context_lines,\n            )?;\n            let rejected: Vec<_> = outcome\n                .rejected_specs\n                .iter()\n                .map(|(reason, spec)| format!(\"{reason:?}: {}\", spec.path))\n                .collect();\n            if !rejected.is_empty() {\n                bail!(\n                    \"Some selected changes no longer match the worktree's uncommitted changes: {}\",\n                    rejected.join(\", \")\n                );\n            }\n            outcome.destination_tree.context(\"No changes to move\")?\n        }\n    };\n    if moved_tree == worktree_head_tree {\n        bail!(\"No changes to move\");\n    }\n\n    let destination_outcome = but_core::worktree::safe_checkout_from_head(\n        moved_tree,\n        main_repo,\n        but_core::worktree::checkout::Options {\n            merge_base_override: Some(worktree_head_tree),\n            allow_uncommitted_changes_to_conflict_with_new_head: true,\n            ..Default::default()","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-workspace/src/worktrees.rs#L185-L221","documentation":"Before moving, the library replays the selected file/hunk specs against the worktree's current uncommitted changes; specs that no longer match are returned in rejected_specs (with a reason). If any spec is rejected, the whole move aborts so the caller never moves a partially stale selection.","triggerScenarios":"Calling move_uncommitted_changes with a selection captured earlier, while the worktree contents changed in the meantime: files edited/created/deleted, hunks shifted by new edits, line counts no longer matching, or the worktree was rebuilt (create_wd_tree) between capture and move.","commonSituations":"An agent selecting hunks, then the user (or a formatter/linter) editing the file before the move executes; retries of a move after a first attempt partially ran; long-running sessions where the worktree drifted; concurrent edits from IDE auto-save.","solutions":["Re-read the current diff and rebuild the selection immediately before moving","Apply the retry pattern: on this error, refresh the selection from fresh worktree state and re-run (the cleanup code already re-runs sweeps on fresh content)","Have the user re-confirm the selection after any edit","Minimize the window between selection capture and move (no formatter/linter hooks in between)"],"exampleFix":"// before: reusing a stale selection\nlet selection = build_selection(&old_diff);\nmove_uncommitted_changes(ctx, &wt, Some(selection), None)?;\n// after: rebuild from the live diff\nlet selection = build_selection(&worktree_repo.create_wd_tree(0)?.diff()?);\nmatch move_uncommitted_changes(ctx, &wt, Some(selection), None) {\n    Err(e) if e.to_string().contains(\"no longer match\") => retry_with_fresh_selection(),\n    r => r,\n}","handlingStrategy":"retry","validationCode":"// rebuild selection from the CURRENT worktree state right before the move\nlet current = worktree_repo.create_wd_tree(0)?;\nlet selection = build_selection(&current.diff()?);\nanyhow::ensure!(!selection.is_empty(), \"nothing to move\");","typeGuard":null,"tryCatchPattern":"match move_uncommitted_changes(ctx, &wt, Some(selection), None) {\n    Err(e) if e.to_string().contains(\"no longer match\") => {\n        let fresh = rebuild_selection_from_live_diff()?;\n        move_uncommitted_changes(ctx, &wt, Some(fresh), None)\n    }\n    r => r,\n}","preventionTips":["Capture and move in one tight window; never persist selections across sessions","Disable formatters/autosave during automated moves","Ask the user to re-confirm after any edit between capture and move","Re-derive selections from the live diff instead of caching them"],"tags":["git","worktree","stale-state","conflict"],"backgroundTag":"invalid-state-transition","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}