{"record":{"id":"7c941b3fac63ffd1","repo":"affaan-m/ECC","slug":"selected-hunk-is-already-staged","errorCode":null,"errorMessage":"selected hunk is already staged","messagePattern":"selected hunk is already staged","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"ecc2/src/worktree/mod.rs","lineNumber":404,"sourceCode":"            &unstaged_patch,\n        ));\n    }\n\n    if sections.is_empty() {\n        Ok(None)\n    } else {\n        Ok(Some(GitStatusPatchView {\n            path: entry.path.clone(),\n            display_path: entry.display_path.clone(),\n            patch: sections.join(\"\\n\\n\"),\n            hunks,\n        }))\n    }\n}\n\npub fn stage_hunk(worktree: &WorktreeInfo, hunk: &GitPatchHunk) -> Result<()> {\n    if hunk.section != GitPatchSectionKind::Unstaged {\n        anyhow::bail!(\"selected hunk is already staged\");\n    }\n    git_apply_patch(\n        &worktree.path,\n        &[\"--cached\"],\n        &hunk.patch,\n        \"stage selected hunk\",\n    )\n}\n\npub fn unstage_hunk(worktree: &WorktreeInfo, hunk: &GitPatchHunk) -> Result<()> {\n    if hunk.section != GitPatchSectionKind::Staged {\n        anyhow::bail!(\"selected hunk is not staged\");\n    }\n    git_apply_patch(\n        &worktree.path,\n        &[\"-R\", \"--cached\"],\n        &hunk.patch,\n        \"unstage selected hunk\",","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/ecc2/src/worktree/mod.rs#L386-L422","documentation":"stage_hunk rejects any hunk whose `section` field is not `GitPatchSectionKind::Unstaged`. This is a precondition guard, not a git failure: the caller handed the function a hunk that lives in the Staged section of the patch view. Staging an already-staged hunk is a no-op the library refuses to perform silently.","triggerScenarios":"Passing a `GitPatchHunk` obtained from the `--- Staged diff ---` section of `git_status_patch_view` into `stage_hunk`. UI dispatches the stage action on the wrong section because it did not check `hunk.section` before choosing the verb.","commonSituations":"TUI list selection drift where the cursor is on a staged hunk but the stage action is still enabled; copy-paste of hunk references across sections; stale hunk object retained after a status refresh moved it to Staged.","solutions":["Before calling stage_hunk, branch on `hunk.section == GitPatchSectionKind::Unstaged`; for Staged hunks either no-op or route to unstage_hunk.","Refresh `git_status_patch_view` immediately before acting so hunk.section reflects current state.","Disable the 'stage' UI affordance when the selected hunk is in the Staged section."],"exampleFix":"// before\nstage_hunk(&worktree, &hunk)?;\n\n// after\nmatch hunk.section {\n    GitPatchSectionKind::Unstaged => stage_hunk(&worktree, &hunk)?,\n    GitPatchSectionKind::Staged => { /* already staged; no-op */ }\n}","handlingStrategy":"validation","validationCode":"use crate::worktree::{GitPatchHunk, GitPatchSectionKind, stage_hunk};\n\nfn try_stage_hunk(worktree: &WorktreeInfo, hunk: &GitPatchHunk) -> anyhow::Result<()> {\n    if hunk.section != GitPatchSectionKind::Unstaged {\n        return Ok(()); // already staged — nothing to do\n    }\n    stage_hunk(worktree, hunk)\n}","typeGuard":"fn is_unstaged(hunk: &GitPatchHunk) -> bool {\n    matches!(hunk.section, GitPatchSectionKind::Unstaged)\n}","tryCatchPattern":"match stage_hunk(&worktree, &hunk) {\n    Ok(()) => { /* refresh */ }\n    Err(e) if format!(\"{e}\").contains(\"already staged\") => { /* benign no-op */ }\n    Err(e) => return Err(e),\n}","preventionTips":["Always branch on `hunk.section` before choosing stage vs unstage.","Refresh `git_status_patch_view` right before acting so section flags are current.","Disable the stage verb when the selected hunk is in the Staged section."],"tags":["git","worktree","state-machine","validation","hunk"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}