{"record":{"id":"ad3b3a24deb2e739","repo":"gitbutlerapp/gitbutler","slug":"no-changes-were-selected-to-move","errorCode":null,"errorMessage":"No changes were selected to move","messagePattern":"No changes were selected to move","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/worktrees.rs","lineNumber":189,"sourceCode":"/// `DiffSpec`s. If `None`, every uncommitted change in the worktree is moved and `context_lines`\n/// is unused.\npub fn move_uncommitted_changes(\n    main_repo: &gix::Repository,\n    worktree_repo: &gix::Repository,\n    selection: Option<Vec<DiffSpec>>,\n    context_lines: u32,\n) -> anyhow::Result<MoveUncommittedChangesOutcome> {\n    let worktree_head_tree = worktree_repo.head_tree_id_or_empty()?.detach();\n\n    let moved_tree = match selection {\n        None =>\n        {\n            #[expect(deprecated)]\n            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            }","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-workspace/src/worktrees.rs#L171-L207","documentation":"move_uncommitted_changes transfers selected uncommitted changes from a linked worktree into the destination, but an explicitly provided selection (Some) that is empty means nothing was chosen. The library treats an empty selection as a caller mistake rather than a silent no-op.","triggerScenarios":"Calling move_uncommitted_changes with Some(selection) where selection.is_empty() — e.g. the UI collected zero hunks/files, the user confirmed a move dialog with nothing ticked, or a filter produced an empty hunk list.","commonSituations":"Agent-driven automation building a selection from a diff that turned out empty; a UI bug sending an empty array instead of None; a user pressing 'move' without selecting any files or hunks.","solutions":["Pass None instead of an empty selection when nothing should move (or skip the call entirely)","Validate the selection is non-empty in the caller/UI before invoking","Rebuild the selection from the current diff if the source list was computed against stale state"],"exampleFix":"// before: forwarding an empty selection\nmove_uncommitted_changes(ctx, &wt, selection /* = [] */, None)?;\n// after: skip when empty\nif selection.as_ref().is_some_and(|s| s.is_empty()) {\n    return Ok(()); // or surface \"nothing selected\" in the UI\n}\nmove_uncommitted_changes(ctx, &wt, selection, None)?;","handlingStrategy":"validation","validationCode":"if let Some(sel) = &selection {\n    anyhow::ensure!(!sel.is_empty(), \"select at least one change to move, or pass None\");\n}","typeGuard":null,"tryCatchPattern":"match move_uncommitted_changes(ctx, &wt, selection, None) {\n    Err(e) if e.to_string().contains(\"No changes were selected\") => {\n        // surface 'nothing selected' in UI or skip as no-op\n    }\n    r => r,\n}","preventionTips":["Pass None (not Some(vec![])) when nothing should move","Validate selections in the UI before invoking","Rebuild selections from the live diff to avoid empty filters","Treat empty selections as an explicit no-op branch in automation"],"tags":["git","worktree","selection","validation"],"backgroundTag":"empty-required-field","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"}